Hint notification

Reads data from hints.ini. Has hyperlinks to highlight settings, toolbars and gizmos.
This commit is contained in:
David Kocik 2021-07-29 13:15:17 +02:00
parent 7fd34e52c1
commit 0d74502aeb
29 changed files with 2116 additions and 197 deletions

168
resources/data/hints.ini Normal file
View File

@ -0,0 +1,168 @@
[hint:Perspective camera]
text = Perspective camera\nDid you know that you can use the <b>K</b> key to quickly switch between an orthographic and perspective camera?
[hint:Camera Views]
text = Camera Views\nDid you know that you can use the number keys <b>0-6</b> to quickly switch between predefined camera angles?
[hint:Place on face]
text = Place on face\nDid you know that you can quickly orient a model so that one of its faces sits on the print bed? Select the<a>Place on face</a>function or press the <b>F</b> key.
hypertext_type = gizmo
hypertext_gizmo_item = place
[hint:Set number of instances]
text = Set number of instances\nDid you know that you can right-click a model and set an exact number of instances instead of copy-pasting it several times?
[hint:Combine infill]
text = Combine infill\nDid you know that you can print the infill with a higher layer height compared to perimeters to save print time using the setting<a>Combine infill every.</a>
hypertext_type = settings
hypertext_settings_opt = infill_every_layers
hypertext_settings_type = 1
hypertext_settings_category = Infill
disabled_modes = SLA; simple
[hint:Hiding sidebar]
text = Hiding sidebar\nDid you know that you can hide the right sidebar using the shortcut <b>Shift+Tab</b>? You can also enable the icon for this from the<a>Preferences.</a>
hypertext_type = preferences
hypertext_preferences_page = 2
[hint:Variable layer height]
text = Variable layer height\nDid you know that you can print different regions of your model with a different layer height and smooth the transitions between them? Try the<a>Variable layer height tool.</a>(Not available for SLA printers.)
hypertext_type = plater
hypertext_plater_item = layersediting
disabled_modes = SLA
[hint:Undo/redo history]
text = Undo/redo history\nDid you know that you can right-click the<a>undo/redo arrows</a>to see the history of changes and to undo or redo several actions at once?
hypertext_type = plater
hypertext_plater_item = undo
[hint:Auto-arrange settings]
text = Auto-arrange settings\nDid you know that you can right-click the<a>auto-arrange icon</a>to adjust the size of the gap between objects and to allow automatic rotations?
hypertext_type = plater
hypertext_plater_item = arrange
[hint:Reload from disk]
text = Reload from disk\nDid you know that if you created a newer version of your model, you can simply reload it in PrusaSlicer? Right-click the model in the 3D view and choose Reload from disk. Read more in the<a>documentation.</a>
hypertext_type = link
hypertext_link = https://help.prusa3d.com/en/article/reload-from-disk_120427
[hint:Different layer height for each model]
text = Different layer height for each model\nDid you know that you can print each model on the plater with a different layer height? Right-click the model in the 3D view, choose Layers and Perimeters and adjust the values in the right panel. Read more in the<a>documentation.</a>
hypertext_type = link
hypertext_link = https://help.prusa3d.com/en/article/per-model-settings_1674
[hint:Solid infill threshold area]
text = Solid infill threshold area\nDid you know that you can make parts of your model with a small cross-section be filled with solid infill automatically? Set the<a>Solid infill threshold area.</a>(Expert mode only.)
hypertext_type = settings
hypertext_settings_opt = solid_infill_below_area
hypertext_settings_type = 1
hypertext_settings_category = Infill
disabled_modes = SLA; simple; advanced
[hint:Search functionality]
text = Search functionality\n Did you know that you use the<a>Search</a>tool to quickly find a specific PrusaSlicer setting? Or use the familiar shortcut <b>Ctrl+F</b>.
hypertext_type = plater
hypertext_plater_item = search
[hint:Box selection]
text = Box selection\nDid you know that you can do a box selection with Shift+Mouse drag? You can also box-deselect objects with <b>Alt+Mouse drag</b>.
[hint:Zoom on selected objects or on all objects if none selected]
text =Zoom on selected objects or on all objects if none selected\nDid you know that you can zoom in on selected objects by pressing the <b>Z</b> key? If none are selected, the camera will zoom on all objects in the scene.
[hint:Shapes gallery]
text = Shapes gallery\nDid you know that PrusaSlicer has a Shapes Gallery? You can use the included models as modifiers, negative volumes or as printable objects. Right-click the platter and select<a>Add Shape - Gallery.</a>
hypertext_type = gallery
disable_modes = simple
[hint:Printable toggle]
text = Printable toggle\nDid you know that you can disable the G-code generation for the selected model without having to move or delete it? Toggle the Printable property of a model from the Right-click context menu.
[hint:Mirror]
text = Mirror\nDid you know that you can mirror the selected model to create a reversed version of it? Right-click the model, select Mirror and pick the mirror axis.
[hint:PageUp / PageDown quick rotation by 45 degrees]
text = PageUp / PageDown quick rotation by 45 degrees\nDid you know that you can quickly rotate selected models by 45 degrees around the Z-axis clockwise or counter-clockwise by pressing <b>Page Up</b> or <b>Page Down</b> respectively?
[hint:Load config from G-code]
text = Load config from G-code\nDid you know that you can use File-Import Config to load print, filament and printer profiles from an existing G-code file? Similarly, you can use File-Import SL1 archive, which also lets you reconstruct 3D models from the voxel data.
[hint:Ironing]
text = Ironing\nDid you know that you can smooth top surfaces of prints using Ironing? The nozzle will run a special second infill phase at the same layer to fill in holes and flatten any lifted plastic. Read more in the<a>documentation.</a> (Requires Advanced or Expert mode.)
hypertext_type = link
hypertext_link = https://help.prusa3d.com/en/article/ironing_177488
disabled_modes = SLA; simple
[hint:Fuzzy skin]
text = Fuzzy skin\nDid you know that you can create rough fibre-like texture on the sides of your models using the<a>Fuzzy skin</a>feature? You can also use modifiers to apply fuzzy-skin only to a portion of your model.
hypertext_type = settings
hypertext_settings_opt = fuzzy_skin
hypertext_settings_type = 1
hypertext_settings_category = Layers and perimeters
disabled_modes = SLA
[hint:Negative volume]
text = Negative volume\nDid you know that you can subtract one mesh from another using the Negative volume modifier? That way you can, for example, create easily resizable holes directly in PrusaSlicer. Read more in the<a>documentation.</a>(Requires Advanced or Expert mode.)
hypertext_type = link
hypertext_link = https://help.prusa3d.com/en/article/negative-volume_238503
disabled_modes = SLA; simple
[hint:Paint-on supports]
text = Paint-on supports\nDid you know that you can paint directly on the object and select areas, where supports should be enforced or blocked? Try the<a>Paint-on supports</a>feature. (Requires Advanced or Expert mode.)
hypertext_type = gizmo
hypertext_gizmo_item = fdm_supports
disabled_modes = SLA; simple
[hint:Paint-on seam]
text = Paint-on seam\nDid you know that you can paint directly on the object and select where to place the start/endpoint of each perimeter loop? Try the<a>Seam painting</a>feature. (Requires Advanced or Expert mode.)
hypertext_type = gizmo
hypertext_gizmo_item = seam
disabled_modes = SLA; simple
[hint:Insert Pause]
text = Insert Pause\nDid you know that you can schedule the print to pause at a specific layer? Right-click the layer slider in the Preview and select Add pause print (M601). This can be used to insert magnets, weights or nuts into your prints. Read more in the<a>documentation.</a>
hypertext_type = link
hypertext_link = https://help.prusa3d.com/en/article/insert-pause-or-custom-g-code-at-layer_120490#insert-pause-at-layer
[hint:Insert Custom G-code]
text = Insert Custom G-code\nDid you know that you can insert a custom G-code at a specific layer? Right-click the layer in the Preview and select Add custom G-code. With this function you can, for example, create a temperature tower. Read more in the<a>documentation.</a>
hypertext_type = link
hypertext_link = https://help.prusa3d.com/en/article/insert-pause-or-custom-g-code-at-layer_120490#insert-custom-g-code-at-layer
[hint:Configuration snapshots]
text = Configuration snapshots\nDid you know that roll back to a complete backup of all system and user profiles? You can view and move back and forth between snapshots using the Configuration - Configuration snapshots menu. Read more in the<a>documentation.</a>
hypertext_type = link
hypertext_link = https://help.prusa3d.com/en/article/configuration-snapshots_1776
[hint:Minimum wall thickness]
text = Minimum wall thickness\nDid you know that instead of the number of top and bottom layers, you can define the<a>Minimum shell thickness</a>in millimeters? This feature is especially useful when using the variable layer height function.
hypertext_type = settings
hypertext_settings_opt = top_solid_min_thickness
hypertext_settings_type = 1
hypertext_settings_category = Layers and perimeters
disabled_modes = SLA
[hint:Settings in non-modal window]
text = Settings in non-modal window\nDid you know that you can open the Settings in a new non-modal window? This means you can have settings open on one screen and the G-code Preview on the other. Go to the<a>Preferences</a>and select Settings in non-modal window.
hypertext_type = preferences
hypertext_preferences_page = 2
[hint:Adaptive infills]
text = Adaptive infills\nDid you know that you can use the Adaptive cubic and Support cubic infills to decrease the print time and lower the filament consumption? Read more in the<a>documentation.</a>
hypertext_type = link
hypertext_link = https://help.prusa3d.com/en/article/infill-patterns_177130
[hint:Fullscreen mode]
text = Fullscreen mode\nDid you know that you can switch PrusaSlicer to fullscreen mode? Use the <b>F11</b> hotkey.
[hint:Simplify mesh]
text = Simplify mesh\nDid you know that you can reduce the number of triangles in a mesh using the Simplify mesh feature? Right-click the model and select Simplify model. Read more in the<a>documentation.</a>
hypertext_type = link
hypertext_link = https://help.prusa3d.com/en/article/simplify-mesh_238941
#[hint:]
#text =
#hypertext =
#follow_text =

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 800 800"
style="enable-background:new 0 0 800 800;"
xml:space="preserve"
sodipodi:docname="notification_left.svg"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"><metadata
id="metadata15"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs13" /><sodipodi:namedview
inkscape:document-rotation="0"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="3840"
inkscape:window-height="2066"
id="namedview11"
showgrid="false"
inkscape:zoom="1.26"
inkscape:cx="400"
inkscape:cy="396.42857"
inkscape:window-x="-11"
inkscape:window-y="-11"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" />
<style
type="text/css"
id="style2">
.st0{fill:#ED6B21;}
</style>
<path
style="stroke-width:0.85"
class="st0"
d="m 296.747,391.51434 155.295,-116.96 v 233.75 l -155.295,-116.79 m -66.64,0 c 0,6.12 2.72,12.155 8.16,16.235 l 229.5,172.635 c 13.43,10.115 32.555,0.51 32.555,-16.235 v -345.355 c 0,-16.745 -19.125,-26.35 -32.555,-16.235 l -229.5,172.805 c -5.44,3.995 -8.16,10.03 -8.16,16.15 z"
id="path6" />
<g
id="g4"
transform="matrix(0.9775,0,0,0.9775,53.547,53.54775)">
<path
id="path2"
class="st0"
d="M 597.2,701.3 H 110.6 C 53.2,701.3 6.5,654.6 6.5,597.2 V 110.6 C 6.5,53.2 53.2,6.5 110.6,6.5 h 486.6 c 57.4,0 104.1,46.7 104.1,104.1 v 486.6 c 0,57.4 -46.7,104.1 -104.1,104.1 z M 110.6,52.4 c -32,0 -58.2,26 -58.2,58.2 v 486.6 c 0,32 26,58.2 58.2,58.2 h 486.6 c 32,0 58.2,-26 58.2,-58.2 V 110.6 c 0,-32 -26,-58.2 -58.2,-58.2 z" />
</g>
<path
style="fill:#ed6b21;fill-opacity:1;stroke-width:0.674603"
d="m 150.65676,738.12999 c -12.4717,-1.39663 -26.66772,-5.94192 -37.84321,-12.11671 -17.754551,-9.80992 -33.768844,-26.68981 -42.418124,-44.71089 -5.985061,-12.4701 -8.760227,-23.35456 -9.821918,-38.52249 -0.48061,-6.8663 -0.640464,-87.42616 -0.497289,-250.61508 0.195544,-222.88027 0.294923,-240.94223 1.356742,-246.58759 4.2349,-22.51562 13.68014,-40.62012 29.200931,-55.97194 14.237938,-14.082924 31.958648,-23.427941 52.602238,-27.739791 5.87892,-1.227937 14.00696,-1.268146 256.3492,-1.268146 h 250.27778 l 7.08334,1.561512 c 21.30688,4.697075 36.90336,13.216072 51.96052,28.381502 14.67865,14.784203 23.1932,30.350373 27.76125,50.752683 l 1.56791,7.00271 v 250.95239 c 0,242.72256 -0.0418,251.15149 -1.26428,257.0238 -9.30592,44.69034 -45.18963,77.43352 -89.75566,81.90028 -9.17898,0.92002 -488.33076,0.87927 -496.55943,-0.0425 z M 652.87275,692.49 c 19.93824,-6.17834 34.6922,-21.42493 40.00111,-41.33675 l 1.51306,-5.67494 V 399.58544 153.69259 l -1.52571,-5.73412 c -5.66288,-21.28292 -21.4158,-36.89778 -42.2051,-41.83523 -5.63965,-1.33941 -7.66026,-1.3488 -253.17948,-1.17613 l -247.49447,0.17405 -4.72222,1.5953 c -18.05932,6.10093 -31.7315,19.23923 -37.4918,36.0278 -1.04762,3.05333 -2.22128,7.52472 -2.60813,9.93642 -0.47859,2.9836 -0.705,81.91876 -0.70847,246.99889 -0.005,218.14117 0.10226,243.1829 1.05916,248.25397 4.27172,22.63802 22.24346,40.86392 44.80877,45.4425 3.58848,0.72811 49.16893,0.87009 250.95237,0.78171 l 246.56747,-0.10801 z"
id="path17" /><path
style="fill:#ed6b21;fill-opacity:1;stroke-width:0.674603"
d="m 497.7111,573.23025 c -2.0645,4.13129 -4.8303,6.86895 -9.4092,9.31331 -3.4365,1.8345 -12.8201,1.79343 -16.5278,-0.0723 -3.224,-1.6224 -232.72361,-174.17372 -235.79014,-177.28102 -3.35765,-3.4022 -4.88322,-7.0012 -5.23218,-12.3432 -0.27168,-4.159 -0.0718,-5.3292 1.51379,-8.8624 1.00474,-2.2388 2.78734,-4.9734 3.96132,-6.0768 4.28582,-4.0281 232.27571,-175.2581 235.54571,-176.9048 4.6586,-2.3458 12.1025,-2.3876 16.5293,-0.093 3.8749,2.0088 7.8054,5.7435 9.6703,9.1887 l 1.4607,2.6984 0.1736,178.1462 0.1736,178.14615 z M 452.042,274.55434 c -1.0035,0.061 -154.9901,116.4878 -154.9901,117.1854 0,0.7118 154.0259,116.84801 154.9901,116.86316 0.2783,0.004 0.5059,-52.66166 0.5059,-117.03566 0,-64.374 -0.2276,-117.0298 -0.5059,-117.0129 z"
id="path19" /></svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
sodipodi:docname="notification_left_hover.svg"
xml:space="preserve"
style="enable-background:new 0 0 800 800;"
viewBox="0 0 800 800"
y="0px"
x="0px"
id="Layer_1"
version="1.1"><metadata
id="metadata15"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs13" /><sodipodi:namedview
inkscape:current-layer="Layer_1"
inkscape:window-maximized="1"
inkscape:window-y="-11"
inkscape:window-x="-11"
inkscape:cy="396.42857"
inkscape:cx="400"
inkscape:zoom="1.26"
showgrid="false"
id="namedview11"
inkscape:window-height="2066"
inkscape:window-width="3840"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
guidetolerance="10"
gridtolerance="10"
objecttolerance="10"
borderopacity="1"
bordercolor="#666666"
pagecolor="#ffffff"
inkscape:document-rotation="0" />
<style
id="style2"
type="text/css">
.st0{fill:#ED6B21;}
</style>
<path
id="path6"
d="m 276.19955,389.92021 186.354,-140.352 v 280.5 l -186.354,-140.148 m -79.968,0 c 0,7.344 3.264,14.586 9.792,19.482 l 275.4,207.162 c 16.116,12.138 39.066,0.612 39.066,-19.482 v -414.426 c 0,-20.094 -22.95,-31.62 -39.066,-19.482 l -275.4,207.366 c -6.528,4.794 -9.792,12.036 -9.792,19.38 z"
class="st0"
style="stroke-width:1.02" />
<g
transform="matrix(1.173,0,0,1.173,-15.64045,-15.6397)"
id="g4">
<path
d="M 597.2,701.3 H 110.6 C 53.2,701.3 6.5,654.6 6.5,597.2 V 110.6 C 6.5,53.2 53.2,6.5 110.6,6.5 h 486.6 c 57.4,0 104.1,46.7 104.1,104.1 v 486.6 c 0,57.4 -46.7,104.1 -104.1,104.1 z M 110.6,52.4 c -32,0 -58.2,26 -58.2,58.2 v 486.6 c 0,32 26,58.2 58.2,58.2 h 486.6 c 32,0 58.2,-26 58.2,-58.2 V 110.6 c 0,-32 -26,-58.2 -58.2,-58.2 z"
class="st0"
id="path2" />
</g>
<path
id="path17"
d="M 100.89126,805.85899 C 85.925222,804.18303 68.889998,798.72868 55.47941,791.31894 34.173949,779.54703 14.956797,759.29116 4.5776612,737.66587 -2.604412,722.70175 -5.9346112,709.6404 -7.2086404,691.43888 -7.7853724,683.19932 -7.9771972,586.52749 -7.8053872,390.70078 -7.5707344,123.24446 -7.4514796,101.57011 -6.1772968,94.795676 -1.0954168,67.776932 10.238871,46.051532 28.86382,27.629348 45.949346,10.729839 67.214198,-0.4841812 91.986506,-5.6584012 99.04121,-7.1319256 108.79486,-7.1801764 399.60555,-7.1801764 h 300.33333 l 8.50001,1.8738144 c 25.56826,5.63649 44.28403,15.859286 62.35262,34.057802 17.61438,17.741044 27.83184,36.420448 33.3135,60.90322 l 1.8815,8.403252 V 399.20078 c 0,291.26707 -0.0502,301.38179 -1.51714,308.42856 -11.1671,53.62841 -54.22756,92.92022 -107.70679,98.28034 -11.01478,1.10402 -585.99691,1.05512 -595.87132,-0.051 z M 703.55045,751.091 c 23.92589,-7.41401 41.63064,-25.70992 48.00133,-49.6041 l 1.81567,-6.80993 V 399.60553 104.53411 L 751.5366,97.653164 C 744.74115,72.11366 725.83764,53.375828 700.89048,47.450888 694.1229,45.843596 691.69817,45.832328 397.07511,46.039532 l -296.99337,0.20886 -5.666662,1.91436 c -21.671184,7.321116 -38.0778,23.087076 -44.99016,43.23336 -1.257144,3.663996 -2.665536,9.029668 -3.129756,11.923708 -0.574308,3.58032 -0.846,98.30251 -0.850164,296.39866 -0.006,261.76941 0.122712,291.81948 1.270992,297.90477 5.126064,27.16562 26.692152,49.0367 53.77052,54.531 4.30618,0.87373 59.00272,1.04411 301.14285,0.93805 l 295.88096,-0.12961 z"
style="fill:#ed6b21;fill-opacity:1;stroke-width:0.809524" /><path
style="fill:#ed6b21;fill-opacity:1;stroke-width:0.809524"
d="m 517.35644,607.97927 c -2.47732,4.95755 -5.79632,8.24274 -11.29098,11.17597 -4.12378,2.2014 -15.3841,2.15212 -19.83334,-0.0868 -3.86886,-1.94688 -279.26835,-209.0085 -282.94818,-212.7372 -4.02918,-4.08265 -5.85987,-8.40144 -6.27862,-14.81191 -0.32601,-4.99079 -0.0862,-6.39496 1.81655,-10.63477 1.20569,-2.68663 3.34481,-5.96811 4.75358,-7.29219 5.14299,-4.83375 278.73085,-210.30981 282.65486,-212.28577 5.59033,-2.81501 14.52301,-2.86511 19.83515,-0.11124 4.64982,2.41053 9.36643,6.89221 11.60431,11.02636 l 1.75284,3.23809 0.20834,213.77545 0.20835,213.77542 z M 462.55355,249.56821 c -1.2042,0.0733 -185.9881,139.7853 -185.9881,140.62241 0,0.85421 184.8311,140.21766 185.9881,140.23584 0.33393,0.005 0.60714,-63.19404 0.60714,-140.44285 0,-77.2488 -0.27321,-140.43574 -0.60714,-140.4154 z"
id="path19" /></svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
sodipodi:docname="notification_preferences.svg"
xml:space="preserve"
style="enable-background:new 0 0 100 100;"
viewBox="0 0 100 100"
y="0px"
x="0px"
id="minimalize_window"
version="1.1"><metadata
id="metadata17"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs15" /><sodipodi:namedview
inkscape:current-layer="minimalize_window"
inkscape:window-maximized="1"
inkscape:window-y="-8"
inkscape:window-x="-8"
inkscape:cy="50"
inkscape:cx="50"
inkscape:zoom="10.08"
showgrid="false"
id="namedview13"
inkscape:window-height="1377"
inkscape:window-width="2560"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
guidetolerance="10"
gridtolerance="10"
objecttolerance="10"
borderopacity="1"
bordercolor="#666666"
pagecolor="#ffffff" />
<style
id="style2"
type="text/css">
.st0{fill:#ED6B21;}
</style>
<g
id="g6">
<path
id="path4"
d="M80,92.8H20c-7.1,0-12.8-5.8-12.8-12.8V20c0-7.1,5.8-12.8,12.8-12.8h60c7.1,0,12.8,5.8,12.8,12.8v60 C92.8,87.1,87.1,92.8,80,92.8z M20,12.8c-4,0-7.2,3.2-7.2,7.2v60c0,3.9,3.2,7.2,7.2,7.2h60c3.9,0,7.2-3.2,7.2-7.2V20 c0-4-3.2-7.2-7.2-7.2H20z"
class="st0" />
</g>
<g
id="g10">
<path
id="path8"
d="M80.5,44l-5.7-0.7c-0.6-2.2-1.4-4.2-2.5-6.2l3.6-4.5c0.5-0.7,0.5-1.8-0.1-2.4l-5.9-5.9 c-0.6-0.6-1.7-0.7-2.4-0.1l-4.5,3.6c-1.9-1.1-4-2-6.1-2.5L56,19.6c-0.1-0.9-0.9-1.6-1.8-1.6h-8.3c-0.9,0-1.7,0.7-1.8,1.6l-0.7,5.7 c-2.2,0.6-4.2,1.4-6.1,2.5l-4.5-3.6c-0.7-0.5-1.8-0.5-2.4,0.1l-5.9,5.9c-0.6,0.6-0.7,1.7-0.1,2.4l3.6,4.5c-1.1,1.9-2,4-2.5,6.1 L19.6,44C18.7,44.1,18,45,18,45.8v8.3c0,0.9,0.7,1.7,1.6,1.8l5.7,0.7c0.6,2.2,1.4,4.2,2.5,6.1l-3.6,4.5c-0.5,0.7-0.5,1.8,0.1,2.4 l5.9,5.9c0.6,0.6,1.7,0.7,2.4,0.1l4.5-3.6c1.9,1.1,4,2,6.1,2.5l0.7,5.7c0.1,0.9,0.9,1.6,1.8,1.6h8.3c0.9,0,1.7-0.7,1.8-1.6l0.7-5.7 c2.2-0.6,4.2-1.4,6.1-2.5l4.5,3.6c0.7,0.5,1.8,0.5,2.4-0.1l5.9-5.9c0.6-0.6,0.7-1.7,0.1-2.4l-3.6-4.5c1.1-1.9,2-4,2.5-6.1l5.7-0.7 c0.9-0.1,1.6-0.9,1.6-1.8v-8.3C82,44.9,81.3,44.1,80.5,44z M50,66.8c-9.3,0-16.8-7.5-16.8-16.8S40.7,33.2,50,33.2 S66.8,40.7,66.8,50S59.3,66.8,50,66.8z"
class="st0" />
</g>
<path
id="path19"
d="M 18.75,92.696085 C 16.846525,92.418222 15.645289,92.057103 14.248486,91.342827 10.768164,89.563113 8.3399658,86.370876 7.4768461,82.440476 7.2982304,81.627112 7.2916667,80.477245 7.2916667,50 c 0,-30.186048 0.00806,-31.633856 0.1805113,-32.417478 C 8.6132236,12.397531 12.392318,8.6115694 17.559524,7.4768461 18.372888,7.2982304 19.522755,7.2916667 50,7.2916667 c 30.186048,0 31.633856,0.00806 32.417478,0.1805113 3.232976,0.7114715 5.949953,2.4425305 7.826838,4.98669 1.078165,1.461476 1.917759,3.360629 2.286745,5.172592 0.168029,0.825133 0.177272,2.515491 0.177272,32.418143 0,30.365281 -0.0069,31.579027 -0.184138,32.385657 -0.592788,2.697863 -1.665191,4.687627 -3.53325,6.555685 -1.820587,1.820588 -3.639881,2.823244 -6.352056,3.500774 l -0.843254,0.210654 -31.39881,0.01496 C 33.12748,92.725556 18.886409,92.716002 18.75,92.696085 Z m 63.033409,-5.68899 c 2.670161,-0.682912 4.81496,-2.945768 5.315692,-5.608285 0.08202,-0.436105 0.104156,-8.923253 0.08281,-31.746032 L 87.152778,18.501984 86.882499,17.708333 C 86.496691,16.575445 85.97299,15.736341 85.118324,14.881675 84.26366,14.02701 83.424556,13.503308 82.291667,13.117501 L 81.498016,12.847222 H 50 18.501984 l -0.793651,0.270279 c -1.132888,0.385807 -1.971992,0.909509 -2.826658,1.764174 -0.854665,0.854666 -1.378367,1.69377 -1.764174,2.826658 l -0.270279,0.793651 -0.02736,31.200397 c -0.0307,35.008562 -0.09842,31.873352 0.723863,33.513124 0.958398,1.911204 2.60508,3.255124 4.642945,3.789286 0.689685,0.180778 1.691694,0.186837 31.772663,0.192128 30.5793,0.0054 31.07235,0.0024 31.82408,-0.189824 z"
style="fill:#ed6b21;stroke-width:0.0992064" /><path
id="path21"
d="m 44.978562,81.556238 c -0.224588,-0.101989 -0.532838,-0.348659 -0.685,-0.548154 -0.25981,-0.340629 -0.296222,-0.518004 -0.597889,-2.912583 -0.176677,-1.402427 -0.35155,-2.806563 -0.388607,-3.120303 -0.04985,-0.42206 -0.107657,-0.570436 -0.222242,-0.570436 -0.426828,0 -3.130028,-1.019464 -4.485271,-1.691541 l -1.535713,-0.761572 -2.217643,1.778586 c -1.219703,0.978222 -2.37837,1.873418 -2.574815,1.989323 -0.425644,0.251135 -1.144099,0.270643 -1.57406,0.04274 -0.427236,-0.226462 -6.56291,-6.418305 -6.684742,-6.745938 -0.156941,-0.422049 -0.124807,-1.076279 0.07174,-1.460661 0.09658,-0.188868 0.985279,-1.352579 1.974895,-2.586024 l 1.799302,-2.242628 -0.575072,-1.130388 c -0.662867,-1.30296 -1.372055,-3.060993 -1.696609,-4.205785 -0.123752,-0.436508 -0.230017,-0.802816 -0.236144,-0.814019 -0.0061,-0.0112 -1.32638,-0.180242 -2.933895,-0.375643 -1.607514,-0.1954 -3.047348,-0.404462 -3.199631,-0.464579 -0.431862,-0.170489 -0.752876,-0.463248 -0.96597,-0.880946 -0.186214,-0.365011 -0.195644,-0.600505 -0.195644,-4.885734 v -4.502237 l 0.230916,-0.437231 c 0.436456,-0.826411 0.686836,-0.90879 4.179995,-1.375297 1.689394,-0.225616 3.075684,-0.419348 3.080644,-0.430516 0.005,-0.01117 0.115383,-0.39977 0.245386,-0.86356 0.343695,-1.226154 0.908071,-2.626283 1.629448,-4.04241 l 0.633472,-1.24356 -1.914391,-2.391737 c -1.866668,-2.332114 -2.229549,-2.912724 -2.092735,-3.348375 0.02325,-0.07405 0.07126,-0.268561 0.10669,-0.432251 0.04712,-0.217734 0.921421,-1.159194 3.257294,-3.507505 1.772449,-1.781888 3.334904,-3.271425 3.512118,-3.348214 0.438165,-0.189863 1.107839,-0.173444 1.519909,0.03726 0.188868,0.09658 1.352579,0.985279 2.586024,1.974895 l 2.242628,1.799302 1.151296,-0.588289 c 1.264016,-0.645888 2.953562,-1.3236 4.184877,-1.678644 0.436508,-0.125864 0.802816,-0.234062 0.814019,-0.240439 0.0112,-0.0064 0.180242,-1.326833 0.375643,-2.934348 0.1954,-1.607514 0.404462,-3.047348 0.464579,-3.199631 0.170489,-0.431862 0.463248,-0.752876 0.880946,-0.96597 0.365084,-0.186251 0.600598,-0.195644 4.905289,-0.195644 4.304692,0 4.540206,0.0094 4.905289,0.195644 0.41844,0.213473 0.711641,0.535411 0.879741,0.96597 0.05945,0.152283 0.313415,1.592373 0.564355,3.200201 0.250941,1.607827 0.465165,2.928375 0.476055,2.93455 0.01089,0.0062 0.332298,0.09235 0.714243,0.191496 1.067209,0.277031 2.798352,0.970587 4.182307,1.675576 l 1.252472,0.638011 2.391738,-1.914391 c 2.611882,-2.090599 2.873711,-2.23593 3.656618,-2.029642 0.366653,0.09661 0.840141,0.527191 3.631513,3.302435 1.783364,1.77306 3.271361,3.333213 3.348214,3.510574 0.189862,0.438165 0.173443,1.107839 -0.03727,1.519909 -0.09658,0.188868 -0.983684,1.350589 -1.971348,2.581602 l -1.795755,2.238205 0.534553,1.085208 c 0.645239,1.309911 1.426175,3.276043 1.731373,4.359017 0.123015,0.436508 0.227955,0.802093 0.233198,0.812412 0.0052,0.01032 1.359355,0.185141 3.009137,0.388494 3.155152,0.388906 3.405425,0.454071 3.747182,0.975657 0.14834,0.226397 0.163254,0.723673 0.149347,4.979853 -0.01647,5.040469 -0.0249,5.133596 -0.511957,5.652039 -0.380147,0.404648 -0.910219,0.526693 -3.819033,0.879306 -1.587713,0.192465 -2.915838,0.349937 -2.951389,0.349937 -0.03555,0 -0.06464,0.0729 -0.06464,0.162006 0,0.432927 -1.014133,3.126418 -1.691162,4.491646 l -0.761194,1.534947 1.91048,2.386851 c 1.862745,2.327215 2.225586,2.907999 2.088823,3.34349 -0.02325,0.07405 -0.07126,0.26856 -0.106691,0.432251 -0.04712,0.217734 -0.92142,1.159193 -3.257293,3.507504 -1.77245,1.781887 -3.334904,3.271425 -3.512118,3.348215 -0.438165,0.189862 -1.107839,0.173443 -1.519909,-0.03727 -0.188868,-0.09658 -1.352579,-0.98528 -2.586025,-1.974896 l -2.242628,-1.799302 -1.130388,0.575073 c -1.302959,0.662866 -3.060993,1.372054 -4.205784,1.696608 -0.436508,0.123752 -0.802817,0.230017 -0.814019,0.236145 -0.0112,0.0061 -0.179836,1.32638 -0.374739,2.933894 -0.357089,2.945162 -0.478368,3.474208 -0.883739,3.855033 -0.528135,0.496158 -0.637275,0.506365 -5.389595,0.504034 -4.124538,-0.002 -4.471911,-0.01546 -4.851013,-0.187615 z m 6.62303,-14.79524 c 2.138902,-0.216686 3.933005,-0.72075 5.797738,-1.62891 7.586919,-3.694968 11.2377,-12.430258 8.574373,-20.516058 -0.413275,-1.254694 -1.457004,-3.302898 -2.260641,-4.436267 -0.85516,-1.206028 -2.686797,-3.037665 -3.892825,-3.892825 -1.133369,-0.803637 -3.181573,-1.847366 -4.436267,-2.260641 -4.232216,-1.394021 -8.811951,-1.092505 -12.7833,0.841615 -7.586197,3.694616 -11.246703,12.45544 -8.572156,20.516058 1.286909,3.878519 4.151034,7.334154 7.715295,9.308687 2.191048,1.213798 4.039987,1.769517 7.016112,2.108768 0.65982,0.07521 1.870159,0.058 2.841671,-0.04043 z"
style="fill:#ed6b21;stroke-width:0.0992064" /></svg>

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="minimalize_window"
x="0px"
y="0px"
viewBox="0 0 100 100"
style="enable-background:new 0 0 100 100;"
xml:space="preserve"
sodipodi:docname="notification_preferences_hover.svg"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"><metadata
id="metadata17"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs15" /><sodipodi:namedview
inkscape:document-rotation="0"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2560"
inkscape:window-height="1377"
id="namedview13"
showgrid="false"
inkscape:zoom="10.08"
inkscape:cx="50"
inkscape:cy="50"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="minimalize_window" />
<style
type="text/css"
id="style2">
.st0{fill:#ED6B21;}
</style>
<g
transform="matrix(1.15,0,0,1.15,-7.5,-7.5)"
id="g6">
<path
class="st0"
d="M 80,92.8 H 20 C 12.9,92.8 7.2,87 7.2,80 V 20 C 7.2,12.9 13,7.2 20,7.2 h 60 c 7.1,0 12.8,5.8 12.8,12.8 v 60 c 0,7.1 -5.7,12.8 -12.8,12.8 z m -60,-80 c -4,0 -7.2,3.2 -7.2,7.2 v 60 c 0,3.9 3.2,7.2 7.2,7.2 h 60 c 3.9,0 7.2,-3.2 7.2,-7.2 V 20 C 87.2,16 84,12.8 80,12.8 Z"
id="path4" />
</g>
<g
transform="matrix(1.15,0,0,1.15,-7.5,-7.5)"
id="g10">
<path
class="st0"
d="m 80.5,44 -5.7,-0.7 c -0.6,-2.2 -1.4,-4.2 -2.5,-6.2 l 3.6,-4.5 c 0.5,-0.7 0.5,-1.8 -0.1,-2.4 L 69.9,24.3 C 69.3,23.7 68.2,23.6 67.5,24.2 L 63,27.8 c -1.9,-1.1 -4,-2 -6.1,-2.5 L 56,19.6 C 55.9,18.7 55.1,18 54.2,18 h -8.3 c -0.9,0 -1.7,0.7 -1.8,1.6 l -0.7,5.7 c -2.2,0.6 -4.2,1.4 -6.1,2.5 L 32.8,24.2 C 32.1,23.7 31,23.7 30.4,24.3 l -5.9,5.9 c -0.6,0.6 -0.7,1.7 -0.1,2.4 l 3.6,4.5 c -1.1,1.9 -2,4 -2.5,6.1 L 19.6,44 C 18.7,44.1 18,45 18,45.8 v 8.3 c 0,0.9 0.7,1.7 1.6,1.8 l 5.7,0.7 c 0.6,2.2 1.4,4.2 2.5,6.1 l -3.6,4.5 c -0.5,0.7 -0.5,1.8 0.1,2.4 l 5.9,5.9 c 0.6,0.6 1.7,0.7 2.4,0.1 L 37.1,72 c 1.9,1.1 4,2 6.1,2.5 l 0.7,5.7 c 0.1,0.9 0.9,1.6 1.8,1.6 H 54 c 0.9,0 1.7,-0.7 1.8,-1.6 l 0.7,-5.7 c 2.2,-0.6 4.2,-1.4 6.1,-2.5 l 4.5,3.6 c 0.7,0.5 1.8,0.5 2.4,-0.1 l 5.9,-5.9 C 76,69 76.1,67.9 75.5,67.2 l -3.6,-4.5 c 1.1,-1.9 2,-4 2.5,-6.1 l 5.7,-0.7 C 81,55.8 81.7,55 81.7,54.1 V 45.8 C 82,44.9 81.3,44.1 80.5,44 Z M 50,66.8 c -9.3,0 -16.8,-7.5 -16.8,-16.8 0,-9.3 7.5,-16.8 16.8,-16.8 9.3,0 16.8,7.5 16.8,16.8 0,9.3 -7.5,16.8 -16.8,16.8 z"
id="path8" />
</g>
<path
style="fill:#ed6b21;stroke-width:0.114087"
d="M 14.0625,99.100498 C 11.873504,98.780955 10.492082,98.365668 8.8857589,97.544251 4.8833886,95.49758 2.0909607,91.826507 1.098373,87.306547 0.89296496,86.371179 0.88541671,85.048832 0.88541671,50 c 0,-34.713955 0.009269,-36.378934 0.20758799,-37.2801 C 2.4052071,6.7571607 6.7511657,2.4033048 12.693453,1.098373 13.628821,0.89296496 14.951168,0.88541671 50,0.88541671 c 34.713955,0 36.378934,0.009269 37.2801,0.20758799 3.717922,0.8181922 6.842446,2.8089101 9.000863,5.7346935 1.23989,1.6806974 2.205423,3.8647238 2.629757,5.9484808 0.193234,0.948903 0.203863,2.892815 0.203863,37.280864 0,34.920074 -0.0079,36.315882 -0.211759,37.243506 -0.681706,3.102542 -1.914969,5.390771 -4.063237,7.539038 -2.093675,2.093676 -4.185863,3.24673 -7.304865,4.02589 l -0.969742,0.242252 -36.108631,0.0172 c -19.859747,0.0095 -36.236979,-0.0015 -36.393849,-0.02443 z m 72.48842,-6.542339 c 3.070686,-0.785349 5.537204,-3.387633 6.113046,-6.449527 0.09432,-0.501521 0.11978,-10.261741 0.09523,-36.507937 l -0.0335,-35.823413 -0.310821,-0.912699 C 91.971195,11.561762 91.368939,10.596792 90.386073,9.6139263 89.403209,8.6310615 88.438239,8.0288042 87.135417,7.5851262 L 86.222718,7.2743053 H 50 13.777282 L 12.864583,7.5851262 C 11.561762,8.0288042 10.596792,8.6310615 9.6139263,9.6139263 8.6310615,10.596792 8.0288042,11.561762 7.5851262,12.864583 l -0.3108209,0.912699 -0.031464,35.880456 c -0.035305,40.259846 -0.113183,36.654355 0.8324425,38.540093 1.1021577,2.197884 2.9958422,3.743392 5.3393872,4.357679 0.793137,0.207894 1.945448,0.214862 36.538562,0.220947 35.166195,0.0062 35.733202,0.0028 36.597692,-0.218298 z"
id="path19" /><path
style="fill:#ed6b21;stroke-width:0.114087"
d="m 44.225346,86.289674 c -0.258276,-0.117288 -0.612763,-0.400958 -0.78775,-0.630377 -0.298781,-0.391724 -0.340655,-0.595705 -0.687572,-3.349471 -0.203179,-1.612791 -0.404283,-3.227547 -0.446898,-3.588348 -0.05733,-0.485369 -0.123806,-0.656002 -0.255578,-0.656002 -0.490853,0 -3.599533,-1.172383 -5.158062,-1.945272 l -1.76607,-0.875808 -2.550289,2.045374 c -1.402659,1.124956 -2.735126,2.154431 -2.961038,2.287722 -0.48949,0.288805 -1.315714,0.311239 -1.810169,0.04915 -0.491321,-0.260432 -7.547346,-7.381051 -7.687453,-7.757829 -0.180482,-0.485356 -0.143528,-1.237721 0.0825,-1.67976 0.111067,-0.217198 1.133071,-1.555466 2.271129,-2.973928 l 2.069198,-2.579022 -0.661333,-1.299946 c -0.762297,-1.498404 -1.577863,-3.520142 -1.951101,-4.836653 -0.142314,-0.501984 -0.264519,-0.923238 -0.271565,-0.936122 -0.007,-0.01288 -1.525337,-0.207278 -3.373979,-0.431989 -1.848642,-0.22471 -3.504451,-0.465131 -3.679576,-0.534266 -0.496641,-0.196062 -0.865807,-0.532735 -1.110866,-1.013088 -0.214146,-0.419763 -0.22499,-0.690581 -0.22499,-5.618594 v -5.177573 l 0.265553,-0.502815 c 0.501925,-0.950373 0.789862,-1.045109 4.806994,-1.581592 1.942804,-0.259458 3.537037,-0.48225 3.542741,-0.495093 0.0057,-0.01285 0.132691,-0.459736 0.282194,-0.993094 0.395249,-1.410077 1.044282,-3.020226 1.873865,-4.648772 l 0.728493,-1.430094 -2.20155,-2.750497 c -2.146668,-2.681931 -2.563981,-3.349633 -2.406645,-3.850631 0.02674,-0.08516 0.08195,-0.308846 0.122694,-0.497089 0.05419,-0.250394 1.059634,-1.333073 3.745888,-4.033631 2.038316,-2.049171 3.835139,-3.762139 4.038935,-3.850446 0.50389,-0.218342 1.274015,-0.199461 1.747896,0.04285 0.217198,0.111067 1.555466,1.133071 2.973927,2.271129 l 2.579023,2.069198 1.32399,-0.676533 c 1.453618,-0.742771 3.396596,-1.52214 4.812608,-1.93044 0.501985,-0.144744 0.923239,-0.269172 0.936122,-0.276505 0.01288,-0.0074 0.207279,-1.525858 0.43199,-3.3745 0.22471,-1.848642 0.465131,-3.504451 0.534266,-3.679576 0.196062,-0.496641 0.532735,-0.865807 1.013088,-1.110866 0.419846,-0.214188 0.690687,-0.22499 5.641082,-0.22499 4.950396,0 5.221237,0.01081 5.641082,0.22499 0.481206,0.245494 0.818387,0.615723 1.011702,1.110866 0.06837,0.175125 0.360428,1.831229 0.649009,3.680231 0.288582,1.849001 0.534939,3.367631 0.547463,3.374733 0.01252,0.0071 0.382143,0.106202 0.821379,0.22022 1.227291,0.318586 3.218105,1.116175 4.809653,1.926912 L 64.97767,24.53555 67.728169,22.334 c 3.003664,-2.404188 3.304768,-2.571319 4.205111,-2.334088 0.421651,0.111102 0.966162,0.60627 4.17624,3.7978 2.050868,2.039019 3.762065,3.833195 3.850446,4.03716 0.218341,0.50389 0.199459,1.274015 -0.04286,1.747896 -0.111067,0.217198 -1.131236,1.553177 -2.26705,2.968842 l -2.065118,2.573936 0.614736,1.247989 c 0.742024,1.506398 1.640101,3.767449 1.991079,5.01287 0.141467,0.501984 0.262148,0.922407 0.268177,0.934273 0.006,0.01187 1.563259,0.212913 3.460508,0.446768 3.628425,0.447242 3.916239,0.522182 4.309259,1.122006 0.170591,0.260357 0.187742,0.832224 0.171749,5.726831 -0.01894,5.796539 -0.02864,5.903635 -0.58875,6.499845 -0.437169,0.465345 -1.046752,0.605697 -4.391888,1.011202 -1.82587,0.221334 -3.353214,0.402427 -3.394098,0.402427 -0.04088,0 -0.07434,0.08384 -0.07434,0.186307 0,0.497866 -1.166253,3.595381 -1.944836,5.165393 l -0.875373,1.765189 2.197052,2.744879 c 2.142157,2.676297 2.559424,3.344199 2.402146,3.845013 -0.02674,0.08516 -0.08195,0.308844 -0.122694,0.497089 -0.05419,0.250394 -1.059633,1.333072 -3.745887,4.03363 -2.038318,2.04917 -3.83514,3.762138 -4.038936,3.850447 -0.50389,0.218341 -1.274015,0.199459 -1.747895,-0.04286 -0.217198,-0.111067 -1.555466,-1.133072 -2.973929,-2.27113 l -2.579022,-2.069197 -1.299946,0.661334 c -1.498403,0.762295 -3.520142,1.577862 -4.836652,1.951099 -0.501984,0.142315 -0.92324,0.264519 -0.936122,0.271566 -0.01288,0.007 -0.206811,1.525337 -0.43095,3.373979 -0.410652,3.386936 -0.550123,3.995339 -1.0163,4.433288 -0.607355,0.570581 -0.732866,0.582319 -6.198034,0.579639 -4.743219,-0.0023 -5.142697,-0.01778 -5.578665,-0.215758 z m 7.616485,-17.014526 c 2.459737,-0.249189 4.522956,-0.828863 6.667399,-1.873247 8.724956,-4.249213 12.923355,-14.294796 9.860528,-23.593466 -0.475266,-1.442899 -1.675554,-3.798333 -2.599737,-5.101708 -0.983434,-1.386932 -3.089816,-3.493314 -4.476748,-4.476748 -1.303375,-0.924183 -3.658809,-2.124471 -5.101707,-2.599737 -4.867049,-1.603125 -10.133744,-1.256381 -14.700795,0.967857 -8.724127,4.248808 -12.933709,14.323756 -9.85798,23.593467 1.479945,4.460296 4.773689,8.434277 8.872589,10.70499 2.519706,1.395867 4.645985,2.034944 8.068529,2.425083 0.758793,0.08649 2.150683,0.0667 3.267922,-0.0465 z"
id="path21" /></svg>

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 800 800"
style="enable-background:new 0 0 800 800;"
xml:space="preserve"
sodipodi:docname="notification_right.svg"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"><metadata
id="metadata15"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs13" /><sodipodi:namedview
inkscape:document-rotation="0"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="3840"
inkscape:window-height="2066"
id="namedview11"
showgrid="false"
inkscape:zoom="2.52"
inkscape:cx="227.47556"
inkscape:cy="335.392"
inkscape:window-x="-11"
inkscape:window-y="-11"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" />
<style
type="text/css"
id="style2">
.st0{fill:#ED6B21;}
</style>
<path
style="stroke-width:0.85"
class="st0"
d="m 501.14231,400.1595 -155.29499,116.96 v -233.75 l 155.29499,116.79 m 66.63999,0 c 0,-6.12 -2.72,-12.155 -8.15999,-16.235 L 330.12233,211.2895 c -13.43,-10.115 -32.555,-0.51 -32.555,16.235 v 345.355 c 0,16.745 19.125,26.35 32.555,16.235 l 229.49998,-172.805 c 5.44,-3.995 8.16,-10.03 8.15999,-16.15 z"
id="path6" />
<g
id="g4"
transform="matrix(0.9775,0,0,0.9775,53.547005,53.547755)">
<path
id="path2"
class="st0"
d="M 597.2,701.3 H 110.6 C 53.2,701.3 6.5,654.6 6.5,597.2 V 110.6 C 6.5,53.2 53.2,6.5 110.6,6.5 h 486.6 c 57.4,0 104.1,46.7 104.1,104.1 v 486.6 c 0,57.4 -46.7,104.1 -104.1,104.1 z M 110.6,52.4 c -32,0 -58.2,26 -58.2,58.2 v 486.6 c 0,32 26,58.2 58.2,58.2 h 486.6 c 32,0 58.2,-26 58.2,-58.2 V 110.6 c 0,-32 -26,-58.2 -58.2,-58.2 z" />
</g>
<path
style="fill:#ed6b21;fill-opacity:1;stroke-width:0.674602"
d="m 150.65676,738.12999 c -12.4717,-1.39663 -26.66772,-5.94191 -37.84321,-12.11671 -17.754565,-9.80992 -33.768845,-26.68981 -42.418125,-44.71089 -5.98506,-12.4701 -8.76024,-23.35456 -9.82192,-38.5225 -0.48062,-6.8663 -0.64046,-87.42616 -0.4973,-250.61508 0.1956,-222.88026 0.29494,-240.94222 1.35676,-246.58758 4.2349,-22.51562 13.68014,-40.62012 29.20092,-55.971935 14.237945,-14.08294 31.958665,-23.42796 52.602245,-27.7398 5.87892,-1.22794 14.00696,-1.26814 256.3492,-1.26814 h 250.27778 l 7.08334,1.5615 c 21.30688,4.69708 36.90336,13.21608 51.96052,28.3815 14.67866,14.784215 23.1932,30.350375 27.76124,50.752695 l 1.56792,7.0027 v 250.9524 c 0,242.72256 -0.0418,251.15148 -1.26428,257.0238 -9.30592,44.69035 -45.18963,77.43352 -89.75567,81.90028 -9.17897,0.92003 -488.33076,0.87926 -496.55942,-0.0426 z m 502.21598,-45.64 c 19.93824,-6.17834 34.6922,-21.42494 40.00112,-41.33676 l 1.51306,-5.67491 V 399.58544 153.69258 l -1.52572,-5.7341 c -5.66288,-21.28292 -21.4158,-36.89778 -42.2051,-41.83524 -5.63964,-1.3394 -7.66026,-1.3488 -253.17948,-1.17612 l -247.49446,0.174 -4.72222,1.5953 c -18.05932,6.10094 -31.7315,19.23924 -37.4918,36.02779 -1.04762,3.05335 -2.22128,7.52472 -2.60814,9.93642 -0.47858,2.98361 -0.705,81.91877 -0.70846,246.99891 -0.004,218.14116 0.1022,243.18289 1.05916,248.25395 4.27172,22.63803 22.24346,40.86392 44.80876,45.44251 3.58848,0.7281 49.16894,0.8701 250.95238,0.7817 l 246.56746,-0.108 z"
id="path17" /><path
style="fill:#ed6b21;fill-opacity:1;stroke-width:0.674602"
d="m 300.17824,218.44362 c 2.06443,-4.13128 4.83026,-6.86894 9.40917,-9.3133 3.43647,-1.83451 12.82007,-1.79344 16.52778,0.0724 3.22403,1.6224 232.7236,174.17374 235.79013,177.281 3.35767,3.4022 4.88323,7.0012 5.23218,12.34324 0.27168,4.159 0.0718,5.32914 -1.5138,8.86232 -1.00471,2.23886 -2.78731,4.97342 -3.96129,6.07682 -4.28583,4.02812 -232.27571,175.25818 -235.54572,176.9048 -4.6586,2.34584 -12.1025,2.3876 -16.52928,0.0928 -3.87486,-2.00878 -7.80538,-5.7435 -9.67029,-9.18862 l -1.46069,-2.69842 -0.1736,-178.1462 -0.1736,-178.14618 z m 45.66908,298.67588 c 1.00351,-0.0612 154.99009,-116.48774 154.99009,-117.18534 0,-0.71184 -154.02593,-116.84804 -154.99009,-116.86318 -0.27827,-0.004 -0.50595,52.66168 -0.50595,117.03568 0,64.37402 0.22768,117.0298 0.50595,117.01284 z"
id="path19" /></svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
sodipodi:docname="notification_right_hover.svg"
xml:space="preserve"
style="enable-background:new 0 0 800 800;"
viewBox="0 0 800 800"
y="0px"
x="0px"
id="Layer_1"
version="1.1"><metadata
id="metadata15"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs13" /><sodipodi:namedview
inkscape:current-layer="Layer_1"
inkscape:window-maximized="1"
inkscape:window-y="-11"
inkscape:window-x="-11"
inkscape:cy="396.42857"
inkscape:cx="400"
inkscape:zoom="1.26"
showgrid="false"
id="namedview11"
inkscape:window-height="2066"
inkscape:window-width="3840"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
guidetolerance="10"
gridtolerance="10"
objecttolerance="10"
borderopacity="1"
bordercolor="#666666"
pagecolor="#ffffff"
inkscape:document-rotation="0" />
<style
id="style2"
type="text/css">
.st0{fill:#ED6B21;}
</style>
<path
id="path6"
d="m 460.47909,399.8897 -93.177,70.176 v -140.25 l 93.177,70.074 m 39.984,0 c 0,-3.672 -1.632,-7.293 -4.896,-9.741 l -137.7,-103.581 c -8.058,-6.069 -19.533,-0.306 -19.533,9.741 v 207.213 c 0,10.047 11.475,15.81 19.533,9.741 l 137.7,-103.683 c 3.264,-2.397 4.896,-6.018 4.896,-9.69 z"
class="st0"
style="stroke-width:0.51" />
<g
transform="matrix(0.5865,0,0,0.5865,191.9219,191.92265)"
id="g4">
<path
d="M 597.2,701.3 H 110.6 C 53.2,701.3 6.5,654.6 6.5,597.2 V 110.6 C 6.5,53.2 53.2,6.5 110.6,6.5 h 486.6 c 57.4,0 104.1,46.7 104.1,104.1 v 486.6 c 0,57.4 -46.7,104.1 -104.1,104.1 z M 110.6,52.4 c -32,0 -58.2,26 -58.2,58.2 v 486.6 c 0,32 26,58.2 58.2,58.2 h 486.6 c 32,0 58.2,-26 58.2,-58.2 V 110.6 c 0,-32 -26,-58.2 -58.2,-58.2 z"
class="st0"
id="path2" />
</g>
<path
id="path17"
d="m 250.18776,602.67199 c -7.48302,-0.83798 -16.00064,-3.56515 -22.70593,-7.27002 -10.65273,-5.88596 -20.26131,-16.01389 -25.45087,-26.82654 -3.59104,-7.48206 -5.25614,-14.01273 -5.89316,-23.11349 -0.28836,-4.11978 -0.38427,-52.4557 -0.29837,-150.36905 0.11733,-133.72816 0.17696,-144.56534 0.81405,-147.95255 2.54094,-13.50937 8.20808,-24.37207 17.52056,-33.58317 8.54276,-8.44975 19.17518,-14.05676 31.56134,-16.64387 3.52735,-0.73676 8.40418,-0.76089 153.80952,-0.76089 h 150.16667 l 4.25,0.93691 c 12.78413,2.81824 22.14202,7.92964 31.17631,17.0289 8.80719,8.87052 13.91592,18.21022 16.65675,30.45161 l 0.94075,4.20163 v 150.57143 c 0,145.63353 -0.0251,150.69089 -0.75857,154.21428 -5.58355,26.8142 -27.11378,46.46011 -53.85339,49.14017 -5.50739,0.55201 -292.99846,0.52756 -297.93567,-0.0255 z M 551.51735,575.288 c 11.96295,-3.707 20.81532,-12.85496 24.00067,-24.80205 l 0.90783,-3.40497 V 399.54526 252.00955 l -0.91542,-3.44047 c -3.39773,-12.76975 -12.84948,-22.13867 -25.32306,-25.10114 -3.38379,-0.80364 -4.59616,-0.80928 -151.90769,-0.70567 l -148.49668,0.10443 -2.83334,0.95718 c -10.83559,3.66055 -19.0389,11.54353 -22.49508,21.61668 -0.62857,1.83199 -1.33276,4.51483 -1.56487,5.96185 -0.28716,1.79016 -0.423,49.15126 -0.42509,148.19933 -0.003,130.8847 0.0614,145.90974 0.6355,148.95238 2.56303,13.58281 13.34608,24.51835 26.88526,27.2655 2.15309,0.43687 29.50136,0.52206 150.57143,0.46903 l 147.94048,-0.0648 z"
style="fill:#ed6b21;fill-opacity:1;stroke-width:0.404762" /><path
id="path19"
d="m 339.90065,290.86016 c 1.23866,-2.47877 2.89816,-4.12137 5.64549,-5.58799 2.06189,-1.1007 7.69205,-1.07605 9.91667,0.0434 1.93443,0.97344 139.63418,104.50426 141.47409,106.36861 2.01459,2.04133 2.92994,4.20072 3.13931,7.40596 0.16301,2.49539 0.0431,3.19748 -0.90827,5.31738 -0.60285,1.34333 -1.67241,2.98406 -2.37679,3.6461 -2.5715,2.41688 -139.36543,105.1549 -141.32744,106.14288 -2.79516,1.4075 -7.2615,1.43255 -9.91757,0.0556 -2.32491,-1.20527 -4.68322,-3.44611 -5.80216,-5.51318 l -0.87642,-1.61905 -0.10417,-106.88772 -0.10417,-106.88771 z m 27.40144,179.20554 c 0.6021,-0.0367 92.99405,-69.89265 92.99405,-70.31121 0,-0.4271 -92.41555,-70.10883 -92.99405,-70.11792 -0.16696,-0.002 -0.30357,31.59702 -0.30357,70.22143 0,38.6244 0.13661,70.21787 0.30357,70.2077 z"
style="fill:#ed6b21;fill-opacity:1;stroke-width:0.404762" /></svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
sodipodi:docname="toolbar_arrow1.svg"
id="svg10"
version="1.1"
viewBox="0 0 119.8 298.8"
height="298.8"
width="119.8">
<metadata
id="metadata16">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs14" />
<sodipodi:namedview
inkscape:current-layer="svg10"
inkscape:window-maximized="0"
inkscape:window-y="0"
inkscape:window-x="0"
inkscape:cy="149.39999"
inkscape:cx="59.900002"
inkscape:zoom="3.3734941"
showgrid="false"
id="namedview12"
inkscape:window-height="1299"
inkscape:window-width="2295"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
guidetolerance="10"
gridtolerance="10"
objecttolerance="10"
borderopacity="1"
bordercolor="#666666"
pagecolor="#ffffff" />
<line
id="line2"
style="fill: none;stroke: #ed6b21;stroke-linecap: round;stroke-miterlimit: 10;stroke-width: 17.007874015748033px"
y2="99.8"
x2="59.2"
y1="290.3"
x1="59.2" />
<line
id="line4"
style="fill: none;stroke: #ed6b21;stroke-linecap: round;stroke-miterlimit: 10;stroke-width: 17.007874015748033px"
y2="8.5"
x2="59.2"
y1="96.6"
x1="8.5" />
<line
id="line6"
style="fill: none;stroke: #ed6b21;stroke-linecap: round;stroke-miterlimit: 10;stroke-width: 17.007874015748033px"
y2="8.5"
x2="59.2"
y1="96.6"
x1="111.2" />
<line
id="line8"
style="fill: none;stroke: #ed6b21;stroke-linecap: round;stroke-miterlimit: 10;stroke-width: 17.007874015748033px"
y2="96.6"
x2="111.2"
y1="96.6"
x1="8.5" />
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -131,8 +131,6 @@ namespace ImGui
const char MaterialIconMarker = 0x8; const char MaterialIconMarker = 0x8;
const char CloseNotifButton = 0xB; const char CloseNotifButton = 0xB;
const char CloseNotifHoverButton = 0xC; const char CloseNotifHoverButton = 0xC;
// const char TimerDotMarker = 0xE;
// const char TimerDotEmptyMarker = 0xF;
const char MinimalizeButton = 0xE; const char MinimalizeButton = 0xE;
const char MinimalizeHoverButton = 0xF; const char MinimalizeHoverButton = 0xF;
const char WarningMarker = 0x10; const char WarningMarker = 0x10;
@ -141,6 +139,12 @@ namespace ImGui
const char EjectHoverButton = 0x13; const char EjectHoverButton = 0x13;
const char CancelButton = 0x14; const char CancelButton = 0x14;
const char CancelHoverButton = 0x15; const char CancelHoverButton = 0x15;
const char LeftArrowButton = 0x16;
const char LeftArrowHoverButton = 0x17;
const char RightArrowButton = 0x18;
const char RightArrowHoverButton = 0x19;
const char PreferencesButton = 0x1A;
const char PreferencesHoverButton = 0x1B;
// void MyFunction(const char* name, const MyMatrix44& v); // void MyFunction(const char* name, const MyMatrix44& v);
} }

View File

@ -170,6 +170,12 @@ void AppConfig::set_defaults()
if (get("show_splash_screen").empty()) if (get("show_splash_screen").empty())
set("show_splash_screen", "1"); set("show_splash_screen", "1");
if (get("last_hint").empty())
set("last_hint", "0");
if (get("show_hints").empty())
set("show_hints", "1");
#ifdef _WIN32 #ifdef _WIN32
if (get("use_legacy_3DConnexion").empty()) if (get("use_legacy_3DConnexion").empty())
set("use_legacy_3DConnexion", "0"); set("use_legacy_3DConnexion", "0");

View File

@ -201,6 +201,8 @@ set(SLIC3R_GUI_SOURCES
GUI/ProjectDirtyStateManager.cpp GUI/ProjectDirtyStateManager.cpp
GUI/DesktopIntegrationDialog.cpp GUI/DesktopIntegrationDialog.cpp
GUI/DesktopIntegrationDialog.hpp GUI/DesktopIntegrationDialog.hpp
GUI/HintNotification.cpp
GUI/HintNotification.hpp
Utils/Http.cpp Utils/Http.cpp
Utils/Http.hpp Utils/Http.hpp
Utils/FixModelByWin10.cpp Utils/FixModelByWin10.cpp

View File

@ -900,6 +900,8 @@ wxDEFINE_EVENT(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, Event<float>);
wxDEFINE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, HeightProfileSmoothEvent); wxDEFINE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, HeightProfileSmoothEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_RELOAD_FROM_DISK, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_RELOAD_FROM_DISK, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_RENDER_TIMER, wxTimerEvent/*RenderTimerEvent*/); wxDEFINE_EVENT(EVT_GLCANVAS_RENDER_TIMER, wxTimerEvent/*RenderTimerEvent*/);
wxDEFINE_EVENT(EVT_GLCANVAS_TOOLBAR_HIGHLIGHTER_TIMER, wxTimerEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_GIZMO_HIGHLIGHTER_TIMER, wxTimerEvent);
const double GLCanvas3D::DefaultCameraZoomToBoxMarginFactor = 1.25; const double GLCanvas3D::DefaultCameraZoomToBoxMarginFactor = 1.25;
@ -2164,6 +2166,10 @@ void GLCanvas3D::bind_event_handlers()
m_canvas->Bind(wxEVT_MOUSEWHEEL, &GLCanvas3D::on_mouse_wheel, this); m_canvas->Bind(wxEVT_MOUSEWHEEL, &GLCanvas3D::on_mouse_wheel, this);
m_canvas->Bind(wxEVT_TIMER, &GLCanvas3D::on_timer, this); m_canvas->Bind(wxEVT_TIMER, &GLCanvas3D::on_timer, this);
m_canvas->Bind(EVT_GLCANVAS_RENDER_TIMER, &GLCanvas3D::on_render_timer, this); m_canvas->Bind(EVT_GLCANVAS_RENDER_TIMER, &GLCanvas3D::on_render_timer, this);
m_toolbar_highlighter.set_timer_owner(m_canvas, 0);
m_canvas->Bind(EVT_GLCANVAS_TOOLBAR_HIGHLIGHTER_TIMER, [this](wxTimerEvent&) { m_toolbar_highlighter.blink(); });
m_gizmo_highlighter.set_timer_owner(m_canvas, 0);
m_canvas->Bind(EVT_GLCANVAS_GIZMO_HIGHLIGHTER_TIMER, [this](wxTimerEvent&) { m_gizmo_highlighter.blink(); });
m_canvas->Bind(wxEVT_LEFT_DOWN, &GLCanvas3D::on_mouse, this); m_canvas->Bind(wxEVT_LEFT_DOWN, &GLCanvas3D::on_mouse, this);
m_canvas->Bind(wxEVT_LEFT_UP, &GLCanvas3D::on_mouse, this); m_canvas->Bind(wxEVT_LEFT_UP, &GLCanvas3D::on_mouse, this);
m_canvas->Bind(wxEVT_MIDDLE_DOWN, &GLCanvas3D::on_mouse, this); m_canvas->Bind(wxEVT_MIDDLE_DOWN, &GLCanvas3D::on_mouse, this);
@ -4399,6 +4405,29 @@ bool GLCanvas3D::_init_main_toolbar()
m_main_toolbar.set_enabled(false); m_main_toolbar.set_enabled(false);
return true; return true;
} }
// init arrow
BackgroundTexture::Metadata arrow_data;
arrow_data.filename = "toolbar_arrow.png";
// arrow_data.filename = "toolbar_arrow.svg";
//arrow_data.left = 16;
//arrow_data.top = 16;
//arrow_data.right = 16;
//arrow_data.bottom = 16;
arrow_data.left = 0;
arrow_data.top = 0;
arrow_data.right = 0;
arrow_data.bottom = 0;
if (!m_main_toolbar.init_arrow(arrow_data))
{
BOOST_LOG_TRIVIAL(error) << "Main toolbar failed to load arrow texture.";
}
if (!m_gizmos.init_arrow(arrow_data))
{
BOOST_LOG_TRIVIAL(error) << "Gizmos manager failed to load arrow texture.";
}
// m_main_toolbar.set_layout_type(GLToolbar::Layout::Vertical); // m_main_toolbar.set_layout_type(GLToolbar::Layout::Vertical);
m_main_toolbar.set_layout_type(GLToolbar::Layout::Horizontal); m_main_toolbar.set_layout_type(GLToolbar::Layout::Horizontal);
@ -5313,6 +5342,11 @@ void GLCanvas3D::_render_gizmos_overlay()
#endif /* __WXMSW__ */ #endif /* __WXMSW__ */
m_gizmos.render_overlay(); m_gizmos.render_overlay();
if (m_gizmo_highlighter.m_render_arrow)
{
m_gizmos.render_arrow(*this, m_gizmo_highlighter.m_gizmo_type);
}
} }
void GLCanvas3D::_render_main_toolbar() void GLCanvas3D::_render_main_toolbar()
@ -5330,6 +5364,10 @@ void GLCanvas3D::_render_main_toolbar()
m_main_toolbar.set_position(top, left); m_main_toolbar.set_position(top, left);
m_main_toolbar.render(*this); m_main_toolbar.render(*this);
if (m_toolbar_highlighter.m_render_arrow)
{
m_main_toolbar.render_arrow(*this, m_toolbar_highlighter.m_toolbar_item);
}
} }
void GLCanvas3D::_render_undoredo_toolbar() void GLCanvas3D::_render_undoredo_toolbar()
@ -6497,6 +6535,24 @@ bool GLCanvas3D::_deactivate_collapse_toolbar_items()
return false; return false;
} }
void GLCanvas3D::highlight_toolbar_item(const std::string& item_name)
{
GLToolbarItem* item = m_main_toolbar.get_item(item_name);
if (!item)
item = m_undoredo_toolbar.get_item(item_name);
if (!item || !item->is_visible())
return;
m_toolbar_highlighter.init(item, this);
}
void GLCanvas3D::highlight_gizmo(const std::string& gizmo_name)
{
GLGizmosManager::EType gizmo = m_gizmos.get_gizmo_from_name(gizmo_name);
if(gizmo == GLGizmosManager::EType::Undefined)
return;
m_gizmo_highlighter.init(&m_gizmos, gizmo, this);
}
const Print* GLCanvas3D::fff_print() const const Print* GLCanvas3D::fff_print() const
{ {
return (m_process == nullptr) ? nullptr : m_process->fff_print(); return (m_process == nullptr) ? nullptr : m_process->fff_print();
@ -6516,10 +6572,119 @@ void GLCanvas3D::WipeTowerInfo::apply_wipe_tower() const
wxGetApp().get_tab(Preset::TYPE_PRINT)->load_config(cfg); wxGetApp().get_tab(Preset::TYPE_PRINT)->load_config(cfg);
} }
void GLCanvas3D::RenderTimer::Notify() void GLCanvas3D::RenderTimer::Notify()
{ {
wxPostEvent((wxEvtHandler*)GetOwner(), RenderTimerEvent( EVT_GLCANVAS_RENDER_TIMER, *this)); wxPostEvent((wxEvtHandler*)GetOwner(), RenderTimerEvent( EVT_GLCANVAS_RENDER_TIMER, *this));
} }
void GLCanvas3D::ToolbarHighlighterTimer::Notify()
{
wxPostEvent((wxEvtHandler*)GetOwner(), ToolbarHighlighterTimerEvent(EVT_GLCANVAS_TOOLBAR_HIGHLIGHTER_TIMER, *this));
}
void GLCanvas3D::GizmoHighlighterTimer::Notify()
{
wxPostEvent((wxEvtHandler*)GetOwner(), GizmoHighlighterTimerEvent(EVT_GLCANVAS_GIZMO_HIGHLIGHTER_TIMER, *this));
}
void GLCanvas3D::ToolbarHighlighter::set_timer_owner(wxEvtHandler* owner, int timerid/* = wxID_ANY*/)
{
m_timer.SetOwner(owner, timerid);
}
void GLCanvas3D::ToolbarHighlighter::init(GLToolbarItem* toolbar_item, GLCanvas3D* canvas)
{
if (m_timer.IsRunning())
invalidate();
if (!toolbar_item || !canvas)
return;
m_timer.Start(300, false);
m_toolbar_item = toolbar_item;
m_canvas = canvas;
}
void GLCanvas3D::ToolbarHighlighter::invalidate()
{
m_timer.Stop();
if (m_toolbar_item) {
m_toolbar_item->set_highlight(GLToolbarItem::EHighlightState::NotHighlighted);
}
m_toolbar_item = nullptr;
m_blink_counter = 0;
m_render_arrow = false;
}
void GLCanvas3D::ToolbarHighlighter::blink()
{
if (m_toolbar_item) {
char state = m_toolbar_item->get_highlight();
if (state != (char)GLToolbarItem::EHighlightState::HighlightedShown)
m_toolbar_item->set_highlight(GLToolbarItem::EHighlightState::HighlightedShown);
else
m_toolbar_item->set_highlight(GLToolbarItem::EHighlightState::HighlightedHidden);
m_render_arrow = !m_render_arrow;
m_canvas->set_as_dirty();
}
else
invalidate();
if ((++m_blink_counter) >= 11)
invalidate();
}
void GLCanvas3D::GizmoHighlighter::set_timer_owner(wxEvtHandler* owner, int timerid/* = wxID_ANY*/)
{
m_timer.SetOwner(owner, timerid);
}
void GLCanvas3D::GizmoHighlighter::init(GLGizmosManager* manager, GLGizmosManager::EType gizmo, GLCanvas3D* canvas)
{
if (m_timer.IsRunning())
invalidate();
if (!gizmo || !canvas)
return;
m_timer.Start(300, false);
m_gizmo_manager = manager;
m_gizmo_type = gizmo;
m_canvas = canvas;
}
void GLCanvas3D::GizmoHighlighter::invalidate()
{
m_timer.Stop();
if (m_gizmo_manager) {
m_gizmo_manager->set_highlight(GLGizmosManager::EType::Undefined, false);
}
m_gizmo_manager = nullptr;
m_gizmo_type = GLGizmosManager::EType::Undefined;
m_blink_counter = 0;
m_render_arrow = false;
}
void GLCanvas3D::GizmoHighlighter::blink()
{
if (m_gizmo_manager) {
if (m_blink_counter % 2 == 0)
m_gizmo_manager->set_highlight(m_gizmo_type, true);
else
m_gizmo_manager->set_highlight(m_gizmo_type, false);
m_render_arrow = !m_render_arrow;
m_canvas->set_as_dirty();
}
else
invalidate();
if ((++m_blink_counter) >= 11)
invalidate();
}
} // namespace GUI } // namespace GUI
} // namespace Slic3r } // namespace Slic3r

View File

@ -93,6 +93,43 @@ private:
wxTimer* m_timer; wxTimer* m_timer;
}; };
class ToolbarHighlighterTimerEvent : public wxEvent
{
public:
ToolbarHighlighterTimerEvent(wxEventType type, wxTimer& timer)
: wxEvent(timer.GetId(), type),
m_timer(&timer)
{
SetEventObject(timer.GetOwner());
}
int GetInterval() const { return m_timer->GetInterval(); }
wxTimer& GetTimer() const { return *m_timer; }
virtual wxEvent* Clone() const { return new ToolbarHighlighterTimerEvent(*this); }
virtual wxEventCategory GetEventCategory() const { return wxEVT_CATEGORY_TIMER; }
private:
wxTimer* m_timer;
};
class GizmoHighlighterTimerEvent : public wxEvent
{
public:
GizmoHighlighterTimerEvent(wxEventType type, wxTimer& timer)
: wxEvent(timer.GetId(), type),
m_timer(&timer)
{
SetEventObject(timer.GetOwner());
}
int GetInterval() const { return m_timer->GetInterval(); }
wxTimer& GetTimer() const { return *m_timer; }
virtual wxEvent* Clone() const { return new GizmoHighlighterTimerEvent(*this); }
virtual wxEventCategory GetEventCategory() const { return wxEVT_CATEGORY_TIMER; }
private:
wxTimer* m_timer;
};
wxDECLARE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, SimpleEvent);
@ -137,6 +174,8 @@ wxDECLARE_EVENT(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, Event<float>);
wxDECLARE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, HeightProfileSmoothEvent); wxDECLARE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, HeightProfileSmoothEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_RELOAD_FROM_DISK, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_RELOAD_FROM_DISK, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_RENDER_TIMER, wxTimerEvent/*RenderTimerEvent*/); wxDECLARE_EVENT(EVT_GLCANVAS_RENDER_TIMER, wxTimerEvent/*RenderTimerEvent*/);
wxDECLARE_EVENT(EVT_GLCANVAS_TOOLBAR_HIGHLIGHTER_TIMER, wxTimerEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_GIZMO_HIGHLIGHTER_TIMER, wxTimerEvent);
class GLCanvas3D class GLCanvas3D
{ {
@ -378,6 +417,16 @@ class GLCanvas3D
virtual void Notify() override; virtual void Notify() override;
}; };
class ToolbarHighlighterTimer : public wxTimer {
private:
virtual void Notify() override;
};
class GizmoHighlighterTimer : public wxTimer {
private:
virtual void Notify() override;
};
public: public:
enum ECursorType : unsigned char enum ECursorType : unsigned char
{ {
@ -517,6 +566,38 @@ private:
SequentialPrintClearance m_sequential_print_clearance; SequentialPrintClearance m_sequential_print_clearance;
bool m_sequential_print_clearance_first_displacement{ true }; bool m_sequential_print_clearance_first_displacement{ true };
struct ToolbarHighlighter
{
void set_timer_owner(wxEvtHandler* owner, int timerid = wxID_ANY);
void init(GLToolbarItem* toolbar_item, GLCanvas3D* canvas);
void blink();
void invalidate();
bool m_render_arrow{ false };
GLToolbarItem* m_toolbar_item{ nullptr };
private:
GLCanvas3D* m_canvas{ nullptr };
int m_blink_counter{ 0 };
ToolbarHighlighterTimer m_timer;
}
m_toolbar_highlighter;
struct GizmoHighlighter
{
void set_timer_owner(wxEvtHandler* owner, int timerid = wxID_ANY);
void init(GLGizmosManager* manager, GLGizmosManager::EType gizmo, GLCanvas3D* canvas);
void blink();
void invalidate();
bool m_render_arrow{ false };
GLGizmosManager::EType m_gizmo_type;
private:
GLGizmosManager* m_gizmo_manager{ nullptr };
GLCanvas3D* m_canvas{ nullptr };
int m_blink_counter{ 0 };
GizmoHighlighterTimer m_timer;
}
m_gizmo_highlighter;
public: public:
explicit GLCanvas3D(wxGLCanvas* canvas); explicit GLCanvas3D(wxGLCanvas* canvas);
~GLCanvas3D(); ~GLCanvas3D();
@ -744,6 +825,9 @@ public:
void use_slope(bool use) { m_slope.use(use); } void use_slope(bool use) { m_slope.use(use); }
void set_slope_normal_angle(float angle_in_deg) { m_slope.set_normal_angle(angle_in_deg); } void set_slope_normal_angle(float angle_in_deg) { m_slope.set_normal_angle(angle_in_deg); }
void highlight_toolbar_item(const std::string& item_name);
void highlight_gizmo(const std::string& gizmo_name);
ArrangeSettings get_arrange_settings() const { ArrangeSettings get_arrange_settings() const {
const ArrangeSettings &settings = get_arrange_settings(this); const ArrangeSettings &settings = get_arrange_settings(this);
ArrangeSettings ret = settings; ArrangeSettings ret = settings;

View File

@ -61,6 +61,7 @@ GLToolbarItem::GLToolbarItem(GLToolbarItem::EType type, const GLToolbarItem::Dat
, m_state(Normal) , m_state(Normal)
, m_data(data) , m_data(data)
, m_last_action_type(Undefined) , m_last_action_type(Undefined)
, m_highlight_state(NotHighlighted)
{ {
} }
@ -91,7 +92,8 @@ void GLToolbarItem::render(unsigned int tex_id, float left, float right, float b
assert((tex_width != 0) && (tex_height != 0)); assert((tex_width != 0) && (tex_height != 0));
GLTexture::Quad_UVs ret; GLTexture::Quad_UVs ret;
// tiles in the texture are spaced by 1 pixel // tiles in the texture are spaced by 1 pixel
float icon_size_px = (float)(tex_width - 1) / (float)Num_States; float icon_size_px = (float)(tex_width - 1) / ((float)Num_States + (float)Num_Rendered_Highlight_States);
char render_state = (m_highlight_state == NotHighlighted ? m_state : Num_States + m_highlight_state);
float inv_tex_width = 1.0f / (float)tex_width; float inv_tex_width = 1.0f / (float)tex_width;
float inv_tex_height = 1.0f / (float)tex_height; float inv_tex_height = 1.0f / (float)tex_height;
// tiles in the texture are spaced by 1 pixel // tiles in the texture are spaced by 1 pixel
@ -99,7 +101,7 @@ void GLToolbarItem::render(unsigned int tex_id, float left, float right, float b
float v_offset = 1.0f * inv_tex_height; float v_offset = 1.0f * inv_tex_height;
float du = icon_size_px * inv_tex_width; float du = icon_size_px * inv_tex_width;
float dv = icon_size_px * inv_tex_height; float dv = icon_size_px * inv_tex_height;
float left = u_offset + (float)m_state * du; float left = u_offset + (float)render_state * du;
float right = left + du - u_offset; float right = left + du - u_offset;
float top = v_offset + (float)m_data.sprite_id * dv; float top = v_offset + (float)m_data.sprite_id * dv;
float bottom = top + dv - v_offset; float bottom = top + dv - v_offset;
@ -183,6 +185,24 @@ bool GLToolbar::init(const BackgroundTexture::Metadata& background_texture)
return res; return res;
} }
bool GLToolbar::init_arrow(const BackgroundTexture::Metadata& arrow_texture)
{
if (m_arrow_texture.texture.get_id() != 0)
return true;
std::string path = resources_dir() + "/icons/";
bool res = false;
if (!arrow_texture.filename.empty())
res = m_arrow_texture.texture.load_from_file(path + arrow_texture.filename, false, GLTexture::SingleThreaded, false);
// res = m_arrow_texture.texture.load_from_svg_file(path + arrow_texture.filename, false, true, false, 100);
if (res)
m_arrow_texture.metadata = arrow_texture;
return res;
}
GLToolbar::Layout::EType GLToolbar::get_layout_type() const GLToolbar::Layout::EType GLToolbar::get_layout_type() const
{ {
return m_layout.type; return m_layout.type;
@ -419,6 +439,8 @@ void GLToolbar::render(const GLCanvas3D& parent)
} }
} }
bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent) bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
{ {
if (!m_enabled) if (!m_enabled)
@ -869,6 +891,21 @@ void GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D&
} }
} }
GLToolbarItem* GLToolbar::get_item(const std::string& item_name)
{
if (!m_enabled)
return nullptr;
for (GLToolbarItem* item : m_items)
{
if (item->get_name() == item_name)
{
return item;
}
}
return nullptr;
}
int GLToolbar::contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const int GLToolbar::contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const
{ {
if (!m_enabled) if (!m_enabled)
@ -1105,6 +1142,63 @@ void GLToolbar::render_background(float left, float top, float right, float bott
} }
} }
void GLToolbar::render_arrow(const GLCanvas3D& parent, GLToolbarItem* highlighted_item)
{
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
float factor = inv_zoom * m_layout.scale;
float scaled_icons_size = m_layout.icons_size * factor;
float scaled_separator_size = m_layout.separator_size * factor;
float scaled_gap_size = m_layout.gap_size * factor;
float border = m_layout.border * factor;
float separator_stride = scaled_separator_size + scaled_gap_size;
float icon_stride = scaled_icons_size + scaled_gap_size;
float left = m_layout.left;
float top = m_layout.top - icon_stride;
for (const GLToolbarItem* item : m_items) {
if (!item->is_visible())
continue;
if (item->is_separator())
left += separator_stride;
else {
if (item->get_name() == highlighted_item->get_name())
break;
left += icon_stride;
}
}
left += border;
top -= separator_stride;
float right = left + scaled_icons_size;
unsigned int tex_id = m_arrow_texture.texture.get_id();
float tex_width = (float)m_icons_texture.get_width();
float tex_height = (float)m_icons_texture.get_height();
if ((tex_id != 0) && (tex_width > 0) && (tex_height > 0)) {
float inv_tex_width = (tex_width != 0.0f) ? 1.0f / tex_width : 0.0f;
float inv_tex_height = (tex_height != 0.0f) ? 1.0f / tex_height : 0.0f;
float internal_left = left + border - scaled_icons_size / 2; // add half scaled_icons_size for huge arrow
float internal_right = right - border + scaled_icons_size / 2;
float internal_top = top - border;
// bottom is not moving and should be calculated from arrow texture sides ratio
float arrow_sides_ratio = (float)m_arrow_texture.texture.get_height() / (float)m_arrow_texture.texture.get_width();
float internal_bottom = internal_top - (internal_right - internal_left) * arrow_sides_ratio;
float internal_left_uv = (float)m_arrow_texture.metadata.left * inv_tex_width;
float internal_right_uv = 1.0f - (float)m_arrow_texture.metadata.right * inv_tex_width;
float internal_top_uv = 1.0f - (float)m_arrow_texture.metadata.top * inv_tex_height;
float internal_bottom_uv = (float)m_arrow_texture.metadata.bottom * inv_tex_height;
GLTexture::render_sub_texture(tex_id, internal_left, internal_right, internal_bottom, internal_top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } });
}
}
void GLToolbar::render_horizontal(const GLCanvas3D& parent) void GLToolbar::render_horizontal(const GLCanvas3D& parent)
{ {
unsigned int tex_id = m_icons_texture.get_id(); unsigned int tex_id = m_icons_texture.get_id();
@ -1217,6 +1311,8 @@ bool GLToolbar::generate_icons_texture()
states.push_back({ 0, false }); // Hover states.push_back({ 0, false }); // Hover
states.push_back({ 0, false }); // HoverPressed states.push_back({ 0, false }); // HoverPressed
states.push_back({ 2, false }); // HoverDisabled states.push_back({ 2, false }); // HoverDisabled
states.push_back({ 0, false }); // HighlightedShown
states.push_back({ 2, false }); // HighlightedHidden
} }
else { else {
states.push_back({ 1, false }); // Normal states.push_back({ 1, false }); // Normal
@ -1225,6 +1321,8 @@ bool GLToolbar::generate_icons_texture()
states.push_back({ 0, false }); // Hover states.push_back({ 0, false }); // Hover
states.push_back({ 1, true }); // HoverPressed states.push_back({ 1, true }); // HoverPressed
states.push_back({ 1, false }); // HoverDisabled states.push_back({ 1, false }); // HoverDisabled
states.push_back({ 0, false }); // HighlightedShown
states.push_back({ 1, false }); // HighlightedHidden
} }
unsigned int sprite_size_px = (unsigned int)(m_layout.icons_size * m_layout.scale); unsigned int sprite_size_px = (unsigned int)(m_layout.icons_size * m_layout.scale);

View File

@ -65,6 +65,14 @@ public:
Num_States Num_States
}; };
enum EHighlightState : unsigned char
{
HighlightedShown,
HighlightedHidden,
Num_Rendered_Highlight_States,
NotHighlighted
};
struct Data struct Data
{ {
struct Option struct Option
@ -104,13 +112,16 @@ private:
EState m_state; EState m_state;
Data m_data; Data m_data;
EActionType m_last_action_type; EActionType m_last_action_type;
EHighlightState m_highlight_state;
public: public:
GLToolbarItem(EType type, const Data& data); GLToolbarItem(EType type, const Data& data);
EState get_state() const { return m_state; } EState get_state() const { return m_state; }
void set_state(EState state) { m_state = state; } void set_state(EState state) { m_state = state; }
EHighlightState get_highlight() const { return m_highlight_state; }
void set_highlight(EHighlightState state) { m_highlight_state = state; }
const std::string& get_name() const { return m_data.name; } const std::string& get_name() const { return m_data.name; }
const std::string& get_icon_filename() const { return m_data.icon_filename; } const std::string& get_icon_filename() const { return m_data.icon_filename; }
const std::string& get_tooltip() const { return m_data.tooltip; } const std::string& get_tooltip() const { return m_data.tooltip; }
@ -143,7 +154,6 @@ public:
bool update_enabled_state(); bool update_enabled_state();
void render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const; void render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const;
private: private:
void set_visible(bool visible) { m_data.visible = visible; } void set_visible(bool visible) { m_data.visible = visible; }
@ -236,6 +246,7 @@ private:
GLTexture m_icons_texture; GLTexture m_icons_texture;
bool m_icons_texture_dirty; bool m_icons_texture_dirty;
BackgroundTexture m_background_texture; BackgroundTexture m_background_texture;
BackgroundTexture m_arrow_texture;
Layout m_layout; Layout m_layout;
ItemsList m_items; ItemsList m_items;
@ -262,6 +273,8 @@ public:
bool init(const BackgroundTexture::Metadata& background_texture); bool init(const BackgroundTexture::Metadata& background_texture);
bool init_arrow(const BackgroundTexture::Metadata& arrow_texture);
Layout::EType get_layout_type() const; Layout::EType get_layout_type() const;
void set_layout_type(Layout::EType type); void set_layout_type(Layout::EType type);
Layout::EHorizontalOrientation get_horizontal_orientation() const { return m_layout.horizontal_orientation; } Layout::EHorizontalOrientation get_horizontal_orientation() const { return m_layout.horizontal_orientation; }
@ -310,9 +323,11 @@ public:
bool update_items_state(); bool update_items_state();
void render(const GLCanvas3D& parent); void render(const GLCanvas3D& parent);
void render_arrow(const GLCanvas3D& parent, GLToolbarItem* highlighted_item);
bool on_mouse(wxMouseEvent& evt, GLCanvas3D& parent); bool on_mouse(wxMouseEvent& evt, GLCanvas3D& parent);
// get item pointer for highlighter timer
GLToolbarItem* get_item(const std::string& item_name);
private: private:
void calc_layout(); void calc_layout();
float get_width_horizontal() const; float get_width_horizontal() const;

View File

@ -661,6 +661,10 @@ void GUI_App::post_init()
this->mainframe->load_config(this->init_params->extra_config); this->mainframe->load_config(this->init_params->extra_config);
} }
// show "Did you know" notification
if (app_config->get("show_hints") == "1")
plater_->get_notification_manager()->push_hint_notification();
// The extra CallAfter() is needed because of Mac, where this is the only way // The extra CallAfter() is needed because of Mac, where this is the only way
// to popup a modal dialog on start without screwing combo boxes. // to popup a modal dialog on start without screwing combo boxes.
// This is ugly but I honestly found no better way to do it. // This is ugly but I honestly found no better way to do it.
@ -1981,6 +1985,43 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
menu->Append(local_menu, _L("&Configuration")); menu->Append(local_menu, _L("&Configuration"));
} }
void GUI_App::open_preferences(size_t open_on_tab)
{
bool app_layout_changed = false;
{
// the dialog needs to be destroyed before the call to recreate_GUI()
// or sometimes the application crashes into wxDialogBase() destructor
// so we put it into an inner scope
PreferencesDialog dlg(mainframe, open_on_tab);
dlg.ShowModal();
app_layout_changed = dlg.settings_layout_changed();
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
if (dlg.seq_top_layer_only_changed() || dlg.seq_seq_top_gcode_indices_changed())
#else
if (dlg.seq_top_layer_only_changed())
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
this->plater_->refresh_print();
#ifdef _WIN32
if (is_editor()) {
if (app_config->get("associate_3mf") == "1")
associate_3mf_files();
if (app_config->get("associate_stl") == "1")
associate_stl_files();
}
else {
if (app_config->get("associate_gcode") == "1")
associate_gcode_files();
}
#endif // _WIN32
}
if (app_layout_changed) {
// hide full main_sizer for mainFrame
mainframe->GetSizer()->Show(false);
mainframe->update_layout();
mainframe->select_tab(size_t(0));
}
}
#if ENABLE_PROJECT_DIRTY_STATE #if ENABLE_PROJECT_DIRTY_STATE
bool GUI_App::has_unsaved_preset_changes() const bool GUI_App::has_unsaved_preset_changes() const
{ {

View File

@ -256,6 +256,8 @@ public:
wxString current_language_code_safe() const; wxString current_language_code_safe() const;
bool is_localized() const { return m_wxLocale->GetLocale() != "English"; } bool is_localized() const { return m_wxLocale->GetLocale() != "English"; }
void open_preferences(size_t open_on_tab = 0);
virtual bool OnExceptionInMainLoop() override; virtual bool OnExceptionInMainLoop() override;
#ifdef __APPLE__ #ifdef __APPLE__

View File

@ -123,10 +123,28 @@ bool GLGizmosManager::init()
m_current = Undefined; m_current = Undefined;
m_hover = Undefined; m_hover = Undefined;
m_highlight = std::pair<EType, bool>(Undefined, false);
return true; return true;
} }
bool GLGizmosManager::init_arrow(const BackgroundTexture::Metadata& arrow_texture)
{
if (m_arrow_texture.texture.get_id() != 0)
return true;
std::string path = resources_dir() + "/icons/";
bool res = false;
if (!arrow_texture.filename.empty())
res = m_arrow_texture.texture.load_from_file(path + arrow_texture.filename, false, GLTexture::SingleThreaded, false);
// res = m_arrow_texture.texture.load_from_svg_file(path + arrow_texture.filename, false, true, false, 100);
if (res)
m_arrow_texture.metadata = arrow_texture;
return res;
}
void GLGizmosManager::set_overlay_icon_size(float size) void GLGizmosManager::set_overlay_icon_size(float size)
{ {
if (m_layout.icons_size != size) if (m_layout.icons_size != size)
@ -973,6 +991,46 @@ void GLGizmosManager::render_background(float left, float top, float right, floa
} }
} }
void GLGizmosManager::render_arrow(const GLCanvas3D& parent, EType highlighted_type) const
{
std::vector<size_t> selectable_idxs = get_selectable_idxs();
if (selectable_idxs.empty())
return;
float cnv_w = (float)m_parent.get_canvas_size().get_width();
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
float height = get_scaled_total_height();
float zoomed_border = m_layout.scaled_border() * inv_zoom;
float zoomed_top_x = (-0.5f * cnv_w) * inv_zoom;
float zoomed_top_y = (0.5f * height) * inv_zoom;
zoomed_top_x += zoomed_border;
zoomed_top_y -= zoomed_border;
float icons_size = m_layout.scaled_icons_size();
float zoomed_icons_size = icons_size * inv_zoom;
float zoomed_stride_y = m_layout.scaled_stride_y() * inv_zoom;
for (size_t idx : selectable_idxs)
{
if (idx == highlighted_type) {
int tex_width = m_icons_texture.get_width();
int tex_height = m_icons_texture.get_height();
unsigned int tex_id = m_arrow_texture.texture.get_id();
float inv_tex_width = (tex_width != 0.0f) ? 1.0f / tex_width : 0.0f;
float inv_tex_height = (tex_height != 0.0f) ? 1.0f / tex_height : 0.0f;
float internal_left_uv = (float)m_arrow_texture.metadata.left * inv_tex_width;
float internal_right_uv = 1.0f - (float)m_arrow_texture.metadata.right * inv_tex_width;
float internal_top_uv = 1.0f - (float)m_arrow_texture.metadata.top * inv_tex_height;
float internal_bottom_uv = (float)m_arrow_texture.metadata.bottom * inv_tex_height;
float arrow_sides_ratio = (float)m_arrow_texture.texture.get_height() / (float)m_arrow_texture.texture.get_width();
GLTexture::render_sub_texture(tex_id, zoomed_top_x + zoomed_icons_size * 1.2f, zoomed_top_x + zoomed_icons_size * 1.2f + zoomed_icons_size * arrow_sides_ratio, zoomed_top_y - zoomed_icons_size, zoomed_top_y, { { internal_left_uv, internal_top_uv }, { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv } });
break;
}
zoomed_top_y -= zoomed_stride_y;
}
}
void GLGizmosManager::do_render_overlay() const void GLGizmosManager::do_render_overlay() const
{ {
std::vector<size_t> selectable_idxs = get_selectable_idxs(); std::vector<size_t> selectable_idxs = get_selectable_idxs();
@ -1012,7 +1070,7 @@ void GLGizmosManager::do_render_overlay() const
if ((icons_texture_id == 0) || (tex_width <= 1) || (tex_height <= 1)) if ((icons_texture_id == 0) || (tex_width <= 1) || (tex_height <= 1))
return; return;
float du = (float)(tex_width - 1) / (4.0f * (float)tex_width); // 4 is the number of possible states if the icons float du = (float)(tex_width - 1) / (6.0f * (float)tex_width); // 6 is the number of possible states if the icons
float dv = (float)(tex_height - 1) / (float)(m_gizmos.size() * tex_height); float dv = (float)(tex_height - 1) / (float)(m_gizmos.size() * tex_height);
// tiles in the texture are spaced by 1 pixel // tiles in the texture are spaced by 1 pixel
@ -1022,9 +1080,9 @@ void GLGizmosManager::do_render_overlay() const
for (size_t idx : selectable_idxs) for (size_t idx : selectable_idxs)
{ {
GLGizmoBase* gizmo = m_gizmos[idx].get(); GLGizmoBase* gizmo = m_gizmos[idx].get();
unsigned int sprite_id = gizmo->get_sprite_id(); unsigned int sprite_id = gizmo->get_sprite_id();
int icon_idx = (m_current == idx) ? 2 : ((m_hover == idx) ? 1 : (gizmo->is_activable()? 0 : 3)); // higlighted state needs to be decided first so its highlighting in every other state
int icon_idx = (m_highlight.first == idx ? (m_highlight.second ? 4 : 5) : (m_current == idx) ? 2 : ((m_hover == idx) ? 1 : (gizmo->is_activable()? 0 : 3)));
float v_top = v_offset + sprite_id * dv; float v_top = v_offset + sprite_id * dv;
float u_left = u_offset + icon_idx * du; float u_left = u_offset + icon_idx * du;
@ -1055,6 +1113,19 @@ GLGizmoBase* GLGizmosManager::get_current() const
return ((m_current == Undefined) || m_gizmos.empty()) ? nullptr : m_gizmos[m_current].get(); return ((m_current == Undefined) || m_gizmos.empty()) ? nullptr : m_gizmos[m_current].get();
} }
GLGizmosManager::EType GLGizmosManager::get_gizmo_from_name(const std::string& gizmo_name) const
{
std::vector<size_t> selectable_idxs = get_selectable_idxs();
for (size_t idx = 0; idx < selectable_idxs.size(); ++idx)
{
std::string filename = m_gizmos[selectable_idxs[idx]]->get_icon_filename();
filename = filename.substr(0, filename.find_first_of('.'));
if (filename == gizmo_name)
return (GLGizmosManager::EType)selectable_idxs[idx];
}
return GLGizmosManager::EType::Undefined;
}
bool GLGizmosManager::generate_icons_texture() const bool GLGizmosManager::generate_icons_texture() const
{ {
std::string path = resources_dir() + "/icons/"; std::string path = resources_dir() + "/icons/";
@ -1074,6 +1145,8 @@ bool GLGizmosManager::generate_icons_texture() const
states.push_back(std::make_pair(0, false)); // Hovered states.push_back(std::make_pair(0, false)); // Hovered
states.push_back(std::make_pair(0, true)); // Selected states.push_back(std::make_pair(0, true)); // Selected
states.push_back(std::make_pair(2, false)); // Disabled states.push_back(std::make_pair(2, false)); // Disabled
states.push_back(std::make_pair(0, false)); // HighlightedShown
states.push_back(std::make_pair(2, false)); // HighlightedHidden
unsigned int sprite_size_px = (unsigned int)m_layout.scaled_icons_size(); unsigned int sprite_size_px = (unsigned int)m_layout.scaled_icons_size();
// // force even size // // force even size

View File

@ -94,9 +94,11 @@ private:
mutable GLTexture m_icons_texture; mutable GLTexture m_icons_texture;
mutable bool m_icons_texture_dirty; mutable bool m_icons_texture_dirty;
BackgroundTexture m_background_texture; BackgroundTexture m_background_texture;
BackgroundTexture m_arrow_texture;
Layout m_layout; Layout m_layout;
EType m_current; EType m_current;
EType m_hover; EType m_hover;
std::pair<EType, bool> m_highlight; // bool true = higlightedShown, false = highlightedHidden
std::vector<size_t> get_selectable_idxs() const; std::vector<size_t> get_selectable_idxs() const;
std::vector<size_t> get_activable_idxs() const; std::vector<size_t> get_activable_idxs() const;
@ -128,6 +130,8 @@ public:
bool init(); bool init();
bool init_arrow(const BackgroundTexture::Metadata& arrow_texture);
template<class Archive> template<class Archive>
void load(Archive& ar) void load(Archive& ar)
{ {
@ -182,6 +186,7 @@ public:
EType get_current_type() const { return m_current; } EType get_current_type() const { return m_current; }
GLGizmoBase* get_current() const; GLGizmoBase* get_current() const;
EType get_gizmo_from_name(const std::string& gizmo_name) const;
bool is_running() const; bool is_running() const;
bool handle_shortcut(int key); bool handle_shortcut(int key);
@ -220,6 +225,8 @@ public:
void render_overlay() const; void render_overlay() const;
void render_arrow(const GLCanvas3D& parent, EType highlighted_type) const;
std::string get_tooltip() const; std::string get_tooltip() const;
bool on_mouse(wxMouseEvent& evt); bool on_mouse(wxMouseEvent& evt);
@ -232,8 +239,13 @@ public:
int get_selectable_icons_cnt() const { return get_selectable_idxs().size(); } int get_selectable_icons_cnt() const { return get_selectable_idxs().size(); }
int get_shortcut_key(GLGizmosManager::EType) const; int get_shortcut_key(GLGizmosManager::EType) const;
// To end highlight set gizmo = undefined
void set_highlight(EType gizmo, bool highlight_shown) { m_highlight = std::pair<EType, bool>(gizmo, highlight_shown); }
bool get_highlight_state() const { return m_highlight.second; }
private: private:
void render_background(float left, float top, float right, float bottom, float border) const; void render_background(float left, float top, float right, float bottom, float border) const;
void do_render_overlay() const; void do_render_overlay() const;
float get_scaled_total_height() const; float get_scaled_total_height() const;

View File

@ -0,0 +1,671 @@
#include "HintNotification.hpp"
#include "ImGuiWrapper.hpp"
#include "format.hpp"
#include "I18N.hpp"
#include "GUI_ObjectList.hpp"
#include "libslic3r/AppConfig.hpp"
#include "libslic3r/Utils.hpp"
#include "libslic3r/Config.hpp"
#include "libslic3r/PresetBundle.hpp"
#include <boost/filesystem.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <map>
namespace Slic3r {
namespace GUI {
const std::string BOLD_MARKER_START = "<b>";
const std::string BOLD_MARKER_END = "</b>";
const std::string HYPERTEXT_MARKER_START = "<a>";
const std::string HYPERTEXT_MARKER_END = "</a>";
namespace {
inline void push_style_color(ImGuiCol idx, const ImVec4& col, bool fading_out, float current_fade_opacity)
{
if (fading_out)
ImGui::PushStyleColor(idx, ImVec4(col.x, col.y, col.z, col.w * current_fade_opacity));
else
ImGui::PushStyleColor(idx, col);
}
// return true if NOT in disabled mode.
inline bool disabled_modes_check(const std::string& disabled_modes)
{
if (disabled_modes.empty())
return true;
// simple / advanced / expert
ConfigOptionMode config_mode = wxGetApp().get_mode();
std::string mode_name;
if (config_mode == ConfigOptionMode::comSimple) mode_name = "simple";
else if (config_mode == ConfigOptionMode::comAdvanced) mode_name = "advanced";
else if (config_mode == ConfigOptionMode::comExpert) mode_name = "expert";
if (!mode_name.empty() && disabled_modes.find(mode_name) != std::string::npos)
return false;
// fff / sla
const PrinterTechnology tech = wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology();
if (tech == ptFFF) {
if (disabled_modes.find("FFF") != std::string::npos)
return false;
} else {
if (disabled_modes.find("SLA") != std::string::npos)
return false;
}
return true;
}
} //namespace
void HintDatabase::init()
{
load_hints_from_file(std::move(boost::filesystem::path(resources_dir()) / "data" / "hints.ini"));
const AppConfig* app_config = wxGetApp().app_config;
m_hint_id = std::atoi(app_config->get("last_hint").c_str());
m_initialized = true;
}
void HintDatabase::load_hints_from_file(const boost::filesystem::path& path)
{
namespace pt = boost::property_tree;
pt::ptree tree;
boost::nowide::ifstream ifs(path.string());
try {
pt::read_ini(ifs, tree);
}
catch (const boost::property_tree::ini_parser::ini_parser_error& err) {
throw Slic3r::RuntimeError(format("Failed loading hints file \"%1%\"\nError: \"%2%\" at line %3%", path, err.message(), err.line()).c_str());
}
for (const auto& section : tree) {
if (boost::starts_with(section.first, "hint:")) {
// create std::map with tree data
std::map<std::string, std::string> dict;
for (const auto& data : section.second) {
dict.emplace(data.first, data.second.data());
}
//unescaping a translating all texts
//unescape text1
std::string fulltext;
std::string text1;
std::string hypertext_text;
std::string follow_text;
std::string disabled_modes;
unescape_string_cstyle(_utf8(dict["text"]), fulltext);
// replace <b> and </b> for imgui markers
std::string marker_s(1, ImGui::ColorMarkerStart);
std::string marker_e(1, ImGui::ColorMarkerEnd);
// start marker
size_t marker_pos = fulltext.find(BOLD_MARKER_START);
while (marker_pos != std::string::npos) {
fulltext.replace(marker_pos, 3, marker_s);
marker_pos = fulltext.find(BOLD_MARKER_START, marker_pos);
}
// end marker
marker_pos = fulltext.find(BOLD_MARKER_END);
while (marker_pos != std::string::npos) {
fulltext.replace(marker_pos, 4, marker_e);
marker_pos = fulltext.find(BOLD_MARKER_END, marker_pos);
}
// divide fulltext
size_t hypertext_start = fulltext.find(HYPERTEXT_MARKER_START);
if (hypertext_start != std::string::npos) {
//hypertext exists
fulltext.erase(hypertext_start, HYPERTEXT_MARKER_START.size());
if (fulltext.find(HYPERTEXT_MARKER_START) != std::string::npos) {
// This must not happen - only 1 hypertext allowed
BOOST_LOG_TRIVIAL(error) << "Hint notification with multiple hypertexts: " << _utf8(dict["text"]);
continue;
}
size_t hypertext_end = fulltext.find(HYPERTEXT_MARKER_END);
if (hypertext_end == std::string::npos) {
// hypertext was not correctly ended
BOOST_LOG_TRIVIAL(error) << "Hint notification without hypertext end marker: " << _utf8(dict["text"]);
continue;
}
fulltext.erase(hypertext_end, HYPERTEXT_MARKER_END.size());
if (fulltext.find(HYPERTEXT_MARKER_END) != std::string::npos) {
// This must not happen - only 1 hypertext end allowed
BOOST_LOG_TRIVIAL(error) << "Hint notification with multiple hypertext end markers: " << _utf8(dict["text"]);
continue;
}
text1 = fulltext.substr(0, hypertext_start);
hypertext_text = fulltext.substr(hypertext_start, hypertext_end - hypertext_start);
follow_text = fulltext.substr(hypertext_end);
} else {
text1 = fulltext;
}
if (dict.find("disabled_modes") != dict.end()) {
disabled_modes = dict["disabled_modes"];
}
// create HintData
if (dict.find("hypertext_type") != dict.end()) {
//link to internet
if(dict["hypertext_type"] == "link") {
std::string hypertext_link = dict["hypertext_link"];
HintData hint_data{ text1, hypertext_text, follow_text, disabled_modes, false, [hypertext_link]() { wxLaunchDefaultBrowser(hypertext_link); } };
m_loaded_hints.emplace_back(hint_data);
// highlight settings
} else if (dict["hypertext_type"] == "settings") {
std::string opt = dict["hypertext_settings_opt"];
Preset::Type type = static_cast<Preset::Type>(std::atoi(dict["hypertext_settings_type"].c_str()));
std::wstring category = boost::nowide::widen(dict["hypertext_settings_category"]);
HintData hint_data{ text1, hypertext_text, follow_text, disabled_modes, true, [opt, type, category]() { GUI::wxGetApp().sidebar().jump_to_option(opt, type, category); } };
m_loaded_hints.emplace_back(hint_data);
// open preferences
} else if(dict["hypertext_type"] == "preferences") {
int page = static_cast<Preset::Type>(std::atoi(dict["hypertext_preferences_page"].c_str()));
HintData hint_data{ text1, hypertext_text, follow_text, disabled_modes, false, [page]() { wxGetApp().open_preferences(page); } };
m_loaded_hints.emplace_back(hint_data);
} else if (dict["hypertext_type"] == "plater") {
std::string item = dict["hypertext_plater_item"];
HintData hint_data{ text1, hypertext_text, follow_text, disabled_modes, true, [item]() { wxGetApp().plater()->canvas3D()->highlight_toolbar_item(item); } };
m_loaded_hints.emplace_back(hint_data);
} else if (dict["hypertext_type"] == "gizmo") {
std::string item = dict["hypertext_gizmo_item"];
HintData hint_data{ text1, hypertext_text, follow_text, disabled_modes, true, [item]() { wxGetApp().plater()->canvas3D()->highlight_gizmo(item); } };
m_loaded_hints.emplace_back(hint_data);
}
else if (dict["hypertext_type"] == "gallery") {
HintData hint_data{ text1, hypertext_text, follow_text, disabled_modes, false, []() { wxGetApp().obj_list()->load_shape_object_from_gallery(); } };
m_loaded_hints.emplace_back(hint_data);
}
} else {
// plain text without hypertext
HintData hint_data{ text1 };
m_loaded_hints.emplace_back(hint_data);
}
}
}
}
HintData* HintDatabase::get_hint(bool up)
{
if (! m_initialized) {
init();
//return false;
}
// shift id
m_hint_id = (up ? m_hint_id + 1 : (m_hint_id == 0 ? m_loaded_hints.size() - 1 : m_hint_id - 1));
m_hint_id %= m_loaded_hints.size();
AppConfig* app_config = wxGetApp().app_config;
app_config->set("last_hint", std::to_string(m_hint_id));
//data = &m_loaded_hints[m_hint_id];
/*
data.text = m_loaded_hints[m_hint_id].text;
data.hypertext = m_loaded_hints[m_hint_id].hypertext;
data.follow_text = m_loaded_hints[m_hint_id].follow_text;
data.callback = m_loaded_hints[m_hint_id].callback;
*/
return &m_loaded_hints[m_hint_id];
}
void NotificationManager::HintNotification::count_spaces()
{
//determine line width
m_line_height = ImGui::CalcTextSize("A").y;
std::string text;
text = ImGui::LeftArrowButton; // TODO change to left arrow
float picture_width = ImGui::CalcTextSize(text.c_str()).x;
m_left_indentation = picture_width + m_line_height / 2;
// no left button picture
//m_left_indentation = m_line_height;
m_window_width_offset = m_left_indentation + m_line_height * 3.f;// 5.5f; // no right arrow
m_window_width = m_line_height * 25;
}
void NotificationManager::HintNotification::count_lines()
{
std::string text = m_text1;
size_t last_end = 0;
m_lines_count = 0;
if (text.empty())
return;
m_endlines.clear();
while (last_end < text.length() - 1)
{
size_t next_hard_end = text.find_first_of('\n', last_end);
if (next_hard_end != std::string::npos && ImGui::CalcTextSize(text.substr(last_end, next_hard_end - last_end).c_str()).x < m_window_width - m_window_width_offset) {
//next line is ended by '/n'
m_endlines.push_back(next_hard_end);
last_end = next_hard_end + 1;
}
else {
// find next suitable endline
if (ImGui::CalcTextSize(text.substr(last_end).c_str()).x >= m_window_width - m_window_width_offset) {
// more than one line till end
size_t next_space = text.find_first_of(' ', last_end);
if (next_space > 0 && next_space < text.length()) {
size_t next_space_candidate = text.find_first_of(' ', next_space + 1);
while (next_space_candidate > 0 && ImGui::CalcTextSize(text.substr(last_end, next_space_candidate - last_end).c_str()).x < m_window_width - m_window_width_offset) {
next_space = next_space_candidate;
next_space_candidate = text.find_first_of(' ', next_space + 1);
}
} else {
next_space = text.length();
}
// when one word longer than line.
if (ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x > m_window_width - m_window_width_offset ||
ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x < (m_window_width - m_window_width_offset) / 4 * 3
) {
float width_of_a = ImGui::CalcTextSize("a").x;
int letter_count = (int)((m_window_width - m_window_width_offset) / width_of_a);
while (last_end + letter_count < text.size() && ImGui::CalcTextSize(text.substr(last_end, letter_count).c_str()).x < m_window_width - m_window_width_offset) {
letter_count++;
}
m_endlines.push_back(last_end + letter_count);
last_end += letter_count;
} else {
m_endlines.push_back(next_space);
last_end = next_space + 1;
}
}
else {
m_endlines.push_back(text.length());
last_end = text.length();
}
}
m_lines_count++;
}
int prev_end = m_endlines.size() > 1 ? m_endlines[m_endlines.size() - 2] : 0;
int size_of_last_line = ImGui::CalcTextSize(text.substr(prev_end, last_end - prev_end).c_str()).x;
// hypertext calculation
if (!m_hypertext.empty()) {
if (size_of_last_line + ImGui::CalcTextSize(m_hypertext.c_str()).x > m_window_width - m_window_width_offset) {
// hypertext on new line
size_of_last_line = ImGui::CalcTextSize((m_hypertext + " ").c_str()).x;
m_endlines.push_back(last_end);
m_lines_count++;
} else {
size_of_last_line += ImGui::CalcTextSize((m_hypertext + " ").c_str()).x;
}
}
if (!m_text2.empty()) {
text = m_text2;
last_end = 0;
m_endlines2.clear();
// if size_of_last_line too large to fit anything
size_t first_end = std::min(text.find_first_of('\n'), text.find_first_of(' '));
if (size_of_last_line >= m_window_width - m_window_width_offset - ImGui::CalcTextSize(text.substr(0, first_end).c_str()).x) {
m_endlines2.push_back(0);
size_of_last_line = 0;
}
while (last_end < text.length() - 1)
{
size_t next_hard_end = text.find_first_of('\n', last_end);
if (next_hard_end != std::string::npos && ImGui::CalcTextSize(text.substr(last_end, next_hard_end - last_end).c_str()).x < m_window_width - m_window_width_offset - size_of_last_line) {
//next line is ended by '/n'
m_endlines2.push_back(next_hard_end);
last_end = next_hard_end + 1;
}
else {
// find next suitable endline
if (ImGui::CalcTextSize(text.substr(last_end).c_str()).x >= m_window_width - m_window_width_offset - size_of_last_line) {
// more than one line till end
size_t next_space = text.find_first_of(' ', last_end);
if (next_space > 0) {
size_t next_space_candidate = text.find_first_of(' ', next_space + 1);
while (next_space_candidate > 0 && ImGui::CalcTextSize(text.substr(last_end, next_space_candidate - last_end).c_str()).x < m_window_width - m_window_width_offset - size_of_last_line) {
next_space = next_space_candidate;
next_space_candidate = text.find_first_of(' ', next_space + 1);
}
}
else {
next_space = text.length();
}
// when one word longer than line.
if (ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x > m_window_width - m_window_width_offset - size_of_last_line ||
ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x + size_of_last_line < (m_window_width - m_window_width_offset) / 4 * 3
) {
float width_of_a = ImGui::CalcTextSize("a").x;
int letter_count = (int)((m_window_width - m_window_width_offset - size_of_last_line) / width_of_a);
while (last_end + letter_count < text.size() && ImGui::CalcTextSize(text.substr(last_end, letter_count).c_str()).x < m_window_width - m_window_width_offset - size_of_last_line) {
letter_count++;
}
m_endlines2.push_back(last_end + letter_count);
last_end += letter_count;
}
else {
m_endlines2.push_back(next_space);
last_end = next_space + 1;
}
}
else {
m_endlines2.push_back(text.length());
last_end = text.length();
}
}
if (size_of_last_line == 0) // if first line is continuation of previous text, do not add to line count.
m_lines_count++;
size_of_last_line = 0; // should countain value only for first line (with hypertext)
}
}
}
void NotificationManager::HintNotification::init()
{
// Do not init closing notification
if (is_finished())
return;
count_spaces();
count_lines();
m_multiline = true;
m_notification_start = GLCanvas3D::timestamp_now();
if (m_state == EState::Unknown)
m_state = EState::Shown;
}
void NotificationManager::HintNotification::set_next_window_size(ImGuiWrapper& imgui)
{
/*
m_window_height = m_multiline ?
(m_lines_count + 1.f) * m_line_height :
4.f * m_line_height;
m_window_height += 1 * m_line_height; // top and bottom
*/
m_window_height = std::max((m_lines_count + 1.f) * m_line_height, 4.f * m_line_height);
}
bool NotificationManager::HintNotification::on_text_click()
{
if (m_hypertext_callback != nullptr && (!m_runtime_disable || disabled_modes_check(m_disabled_modes)))
m_hypertext_callback();
return false;
}
void NotificationManager::HintNotification::render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
if (!m_has_hint_data) {
retrieve_data();
}
float x_offset = m_left_indentation;
int last_end = 0;
float starting_y = (m_lines_count == 2 ? win_size_y / 2 - m_line_height :(m_lines_count == 1 ? win_size_y / 2 - m_line_height / 2: m_line_height / 2));
float shift_y = m_line_height;
std::string line;
for (size_t i = 0; i < (m_multiline ? /*m_lines_count*/m_endlines.size() : 2); i++) {
line.clear();
ImGui::SetCursorPosX(x_offset);
ImGui::SetCursorPosY(starting_y + i * shift_y);
if (m_endlines.size() > i && m_text1.size() >= m_endlines[i]) {
if (i == 1 && m_endlines.size() > 2 && !m_multiline) {
// second line with "more" hypertext
line = m_text1.substr(m_endlines[0] + (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0), m_endlines[1] - m_endlines[0] - (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0));
while (ImGui::CalcTextSize(line.c_str()).x > m_window_width - m_window_width_offset - ImGui::CalcTextSize((".." + _u8L("More")).c_str()).x) {
line = line.substr(0, line.length() - 1);
}
line += "..";
} else {
// regural line
line = m_text1.substr(last_end, m_endlines[i] - last_end);
}
// first line is headline
if (i == 0) {
line = ImGui::ColorMarkerStart + line + ImGui::ColorMarkerEnd;
}
// Add ImGui::ColorMarkerStart if there is ImGui::ColorMarkerEnd first (start was at prev line)
if (line.find_first_of(ImGui::ColorMarkerEnd) < line.find_first_of(ImGui::ColorMarkerStart)) {
line = ImGui::ColorMarkerStart + line;
}
last_end = m_endlines[i];
if (m_text1.size() > m_endlines[i])
last_end += (m_text1[m_endlines[i]] == '\n' || m_text1[m_endlines[i]] == ' ' ? 1 : 0);
imgui.text(line.c_str());
}
}
//hyperlink text
if (!m_multiline && m_lines_count > 2) {
render_hypertext(imgui, x_offset + ImGui::CalcTextSize((line + " ").c_str()).x, starting_y + shift_y, _u8L("More"), true);
} else if (!m_hypertext.empty()) {
render_hypertext(imgui, x_offset + ImGui::CalcTextSize((line + (line.empty()? "": " ")).c_str()).x, starting_y + (m_endlines.size() - 1) * shift_y, m_hypertext);
}
// text2
if (!m_text2.empty() && m_multiline) {
starting_y += (m_endlines.size() - 1) * shift_y;
last_end = 0;
for (size_t i = 0; i < (m_multiline ? m_endlines2.size() : 2); i++) {
if (i == 0) //first line X is shifted by hypertext
ImGui::SetCursorPosX(x_offset + ImGui::CalcTextSize((line + m_hypertext + (line.empty() ? " " : " ")).c_str()).x);
else
ImGui::SetCursorPosX(x_offset);
ImGui::SetCursorPosY(starting_y + i * shift_y);
line.clear();
if (m_endlines2.size() > i && m_text2.size() >= m_endlines2[i]) {
// regural line
line = m_text2.substr(last_end, m_endlines2[i] - last_end);
// Add ImGui::ColorMarkerStart if there is ImGui::ColorMarkerEnd first (start was at prev line)
if (line.find_first_of(ImGui::ColorMarkerEnd) < line.find_first_of(ImGui::ColorMarkerStart)) {
line = ImGui::ColorMarkerStart + line;
}
last_end = m_endlines2[i];
if (m_text2.size() > m_endlines2[i])
last_end += (m_text2[m_endlines2[i]] == '\n' || m_text2[m_endlines2[i]] == ' ' ? 1 : 0);
imgui.text(line.c_str());
}
}
}
}
void NotificationManager::HintNotification::render_close_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
ImVec2 win_size(win_size_x, win_size_y);
ImVec2 win_pos(win_pos_x, win_pos_y);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
std::string button_text;
button_text = ImGui::CloseNotifButton;
if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - win_size.x / 10.f, win_pos.y),
ImVec2(win_pos.x, win_pos.y + win_size.y - 2 * m_line_height),
true))
{
button_text = ImGui::CloseNotifHoverButton;
}
ImVec2 button_pic_size = ImGui::CalcTextSize(button_text.c_str());
ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f);
m_close_b_w = button_size.y;
if (m_lines_count <= 3) {
m_close_b_y = win_size.y / 2 - button_size.y * 1.25f;
ImGui::SetCursorPosX(win_size.x - m_line_height * 2.75f);
ImGui::SetCursorPosY(m_close_b_y);
} else {
ImGui::SetCursorPosX(win_size.x - m_line_height * 2.75f);
ImGui::SetCursorPosY(win_size.y / 2 - button_size.y);
}
if (imgui.button(button_text.c_str(), button_size.x, button_size.y))
{
close();
}
//invisible large button
ImGui::SetCursorPosX(win_size.x - m_line_height * 2.35f);
ImGui::SetCursorPosY(0);
if (imgui.button(" ", m_line_height * 2.125, win_size.y - 2 * m_line_height))
{
close();
}
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
render_right_arrow_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
render_logo(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
render_preferences_button(imgui, win_pos_x, win_pos_y);
}
void NotificationManager::HintNotification::render_preferences_button(ImGuiWrapper& imgui, const float win_pos_x, const float win_pos_y)
{
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
push_style_color(ImGuiCol_ButtonActive, ImGui::GetStyleColorVec4(ImGuiCol_WindowBg), m_state == EState::FadingOut, m_current_fade_opacity);
push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
std::string button_text;
button_text = ImGui::PreferencesButton;
//hover
if (ImGui::IsMouseHoveringRect(ImVec2(win_pos_x - m_window_width / 10.f, win_pos_y + m_window_height - 2 * m_line_height + 1),
ImVec2(win_pos_x, win_pos_y + m_window_height),
true))
{
button_text = ImGui::PreferencesHoverButton;
}
ImVec2 button_pic_size = ImGui::CalcTextSize(button_text.c_str());
ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f);
ImGui::SetCursorPosX(m_window_width - m_line_height * 1.75f);
if (m_lines_count <= 3) {
ImGui::SetCursorPosY(m_close_b_y + m_close_b_w / 4.f * 7.f);
} else {
ImGui::SetCursorPosY(m_window_height - button_size.y - m_close_b_w / 4.f);
}
if (imgui.button(button_text.c_str(), button_size.x, button_size.y))
{
wxGetApp().open_preferences(2);
}
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
// preferences button is in place of minimize button
m_minimize_b_visible = true;
}
void NotificationManager::HintNotification::render_right_arrow_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
// Used for debuging
ImVec2 win_size(win_size_x, win_size_y);
ImVec2 win_pos(win_pos_x, win_pos_y);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
std::string button_text;
button_text = ImGui::RightArrowButton;
ImVec2 button_pic_size = ImGui::CalcTextSize(button_text.c_str());
ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f);
ImGui::SetCursorPosX(m_window_width - m_line_height * 3.f);
if (m_lines_count <= 3)
ImGui::SetCursorPosY(m_close_b_y + m_close_b_w / 4.f * 7.f);
else
ImGui::SetCursorPosY(m_window_height - button_size.y - m_close_b_w / 4.f);
if (imgui.button(button_text.c_str(), button_size.x * 0.8f, button_size.y * 1.f))
{
retrieve_data();
}
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
}
void NotificationManager::HintNotification::render_logo(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
ImVec2 win_size(win_size_x, win_size_y);
ImVec2 win_pos(win_pos_x, win_pos_y);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
std::string button_text;
button_text = ImGui::ErrorMarker;//LeftArrowButton;
ImVec2 button_pic_size = ImGui::CalcTextSize(button_text.c_str());
ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f);
ImGui::SetCursorPosY(win_size.y / 2 - button_size.y);
ImGui::SetCursorPosX(0);
// shouldnt it render as text?
if (imgui.button(button_text.c_str(), button_size.x, button_size.y))
{
}
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
}
void NotificationManager::HintNotification::retrieve_data(size_t recursion_counter)
{
HintData* hint_data = HintDatabase::get_instance().get_hint(true);
if (hint_data != nullptr && !disabled_modes_check(hint_data->disabled_modes))
{
// Content for different user - retrieve another
size_t count = HintDatabase::get_instance().get_count();
if (count < recursion_counter) {
BOOST_LOG_TRIVIAL(error) << "Hint notification failed to load data due to recursion counter.";
} else {
retrieve_data(recursion_counter + 1);
}
return;
}
if(hint_data != nullptr)
{
NotificationData nd { NotificationType::DidYouKnowHint,
NotificationLevel::RegularNotification,
0,
hint_data->text,
hint_data->hypertext, nullptr,
hint_data->follow_text };
update(nd);
m_hypertext_callback = hint_data->callback;
m_disabled_modes = hint_data->disabled_modes;
m_runtime_disable = hint_data->runtime_disable;
m_has_hint_data = true;
}
}
} //namespace Slic3r
} //namespace GUI

View File

@ -0,0 +1,97 @@
#ifndef slic3r_GUI_HintNotification_hpp_
#define slic3r_GUI_HintNotification_hpp_
#include "NotificationManager.hpp"
namespace Slic3r {
namespace GUI {
// Database of hints updatable
struct HintData
{
std::string text;
std::string hypertext;
std::string follow_text;
std::string disabled_modes;
bool runtime_disable; // if true - hyperlink will check before every click if not in disabled mode
std::function<void(void)> callback{ nullptr };
};
class HintDatabase
{
public:
static HintDatabase& get_instance()
{
static HintDatabase instance; // Guaranteed to be destroyed.
// Instantiated on first use.
return instance;
}
private:
HintDatabase()
: m_hint_id(0)
{}
public:
HintDatabase(HintDatabase const&) = delete;
void operator=(HintDatabase const&) = delete;
// return true if HintData filled;
HintData* get_hint(bool up = true);
size_t get_count() {
if (!m_initialized)
return 0;
return m_loaded_hints.size();
}
private:
void init();
void load_hints_from_file(const boost::filesystem::path& path);
size_t m_hint_id;
bool m_initialized { false };
std::vector<HintData> m_loaded_hints;
};
// Notification class - shows current Hint ("Did you know")
class NotificationManager::HintNotification : public NotificationManager::PopNotification
{
public:
HintNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler)
: PopNotification(n, id_provider, evt_handler)
{
retrieve_data();
}
virtual void init() override;
protected:
virtual void set_next_window_size(ImGuiWrapper& imgui) override;
virtual void count_spaces() override;
virtual void count_lines() override;
virtual bool on_text_click() override;
virtual void render_text(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y) override;
virtual void render_close_button(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y) override;
virtual void render_minimize_button(ImGuiWrapper& imgui,
const float win_pos_x, const float win_pos_y) override {}
void render_preferences_button(ImGuiWrapper& imgui,
const float win_pos_x, const float win_pos_y);
void render_right_arrow_button(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y);
void render_logo(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y);
void retrieve_data(size_t recursion_counter = 0);
bool m_has_hint_data { false };
std::function<void(void)> m_hypertext_callback;
std::string m_disabled_modes;
bool m_runtime_disable;
float m_close_b_y { 0 };
float m_close_b_w { 0 };
};
} //namespace Slic3r
} //namespace GUI
#endif //slic3r_GUI_HintNotification_hpp_

View File

@ -43,7 +43,11 @@ static const std::map<const char, std::string> font_icons = {
{ImGui::FilamentIconMarker , "spool" }, {ImGui::FilamentIconMarker , "spool" },
{ImGui::MaterialIconMarker , "resin" }, {ImGui::MaterialIconMarker , "resin" },
{ImGui::MinimalizeButton , "notification_minimalize" }, {ImGui::MinimalizeButton , "notification_minimalize" },
{ImGui::MinimalizeHoverButton , "notification_minimalize_hover" } {ImGui::MinimalizeHoverButton , "notification_minimalize_hover" },
{ImGui::RightArrowButton , "notification_right" },
{ImGui::RightArrowHoverButton , "notification_right_hover" },
{ImGui::PreferencesButton , "notification_preferences" },
{ImGui::PreferencesHoverButton , "notification_preferences_hover"},
}; };
static const std::map<const char, std::string> font_icons_large = { static const std::map<const char, std::string> font_icons_large = {
{ImGui::CloseNotifButton , "notification_close" }, {ImGui::CloseNotifButton , "notification_close" },
@ -54,6 +58,8 @@ static const std::map<const char, std::string> font_icons_large = {
{ImGui::ErrorMarker , "notification_error" }, {ImGui::ErrorMarker , "notification_error" },
{ImGui::CancelButton , "notification_cancel" }, {ImGui::CancelButton , "notification_cancel" },
{ImGui::CancelHoverButton , "notification_cancel_hover" }, {ImGui::CancelHoverButton , "notification_cancel_hover" },
{ImGui::LeftArrowButton , "notification_left" },
{ImGui::LeftArrowHoverButton , "notification_left_hover" },
}; };
const ImVec4 ImGuiWrapper::COL_GREY_DARK = { 0.333f, 0.333f, 0.333f, 1.0f }; const ImVec4 ImGuiWrapper::COL_GREY_DARK = { 0.333f, 0.333f, 0.333f, 1.0f };

View File

@ -1,10 +1,11 @@
#include "NotificationManager.hpp" #include "NotificationManager.hpp"
#include "HintNotification.hpp"
#include "GUI.hpp" #include "GUI.hpp"
#include "ImGuiWrapper.hpp" #include "ImGuiWrapper.hpp"
#include "PrintHostDialogs.hpp" #include "PrintHostDialogs.hpp"
#include "wxExtensions.hpp" #include "wxExtensions.hpp"
#include "libslic3r/Config.hpp"
#include "../Utils/PrintHost.hpp" #include "../Utils/PrintHost.hpp"
#include "libslic3r/Config.hpp" #include "libslic3r/Config.hpp"
@ -30,7 +31,37 @@ wxDEFINE_EVENT(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, EjectDriveNotificationClicke
wxDEFINE_EVENT(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, ExportGcodeNotificationClickedEvent); wxDEFINE_EVENT(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, ExportGcodeNotificationClickedEvent);
wxDEFINE_EVENT(EVT_PRESET_UPDATE_AVAILABLE_CLICKED, PresetUpdateAvailableClickedEvent); wxDEFINE_EVENT(EVT_PRESET_UPDATE_AVAILABLE_CLICKED, PresetUpdateAvailableClickedEvent);
namespace Notifications_Internal{ const NotificationManager::NotificationData NotificationManager::basic_notifications[] = {
{NotificationType::Mouse3dDisconnected, NotificationLevel::RegularNotification, 10, _u8L("3D Mouse disconnected.") },
{NotificationType::PresetUpdateAvailable, NotificationLevel::ImportantNotification, 20, _u8L("Configuration update is available."), _u8L("See more."),
[](wxEvtHandler* evnthndlr) {
if (evnthndlr != nullptr)
wxPostEvent(evnthndlr, PresetUpdateAvailableClickedEvent(EVT_PRESET_UPDATE_AVAILABLE_CLICKED));
return true;
}
},
{NotificationType::NewAppAvailable, NotificationLevel::ImportantNotification, 20, _u8L("New version is available."), _u8L("See Releases page."), [](wxEvtHandler* evnthndlr) {
wxLaunchDefaultBrowser("https://github.com/prusa3d/PrusaSlicer/releases"); return true; }},
{NotificationType::EmptyColorChangeCode, NotificationLevel::RegularNotification, 10,
_u8L("You have just added a G-code for color change, but its value is empty.\n"
"To export the G-code correctly, check the \"Color Change G-code\" in \"Printer Settings > Custom G-code\"") },
{NotificationType::EmptyAutoColorChange, NotificationLevel::RegularNotification, 10,
_u8L("This model doesn't allow to automatically add the color changes") },
{NotificationType::DesktopIntegrationSuccess, NotificationLevel::RegularNotification, 10,
_u8L("Desktop integration was successful.") },
{NotificationType::DesktopIntegrationFail, NotificationLevel::WarningNotification, 10,
_u8L("Desktop integration failed.") },
{NotificationType::UndoDesktopIntegrationSuccess, NotificationLevel::RegularNotification, 10,
_u8L("Undo desktop integration was successful.") },
{NotificationType::UndoDesktopIntegrationFail, NotificationLevel::WarningNotification, 10,
_u8L("Undo desktop integration failed.") },
//{NotificationType::NewAppAvailable, NotificationLevel::ImportantNotification, 20, _u8L("New vesion of PrusaSlicer is available.", _u8L("Download page.") },
//{NotificationType::LoadingFailed, NotificationLevel::RegularNotification, 20, _u8L("Loading of model has Failed") },
//{NotificationType::DeviceEjected, NotificationLevel::RegularNotification, 10, _u8L("Removable device has been safely ejected")} // if we want changeble text (like here name of device), we need to do it as CustomNotification
};
namespace {
/* // not used?
ImFont* add_default_font(float pixel_size) ImFont* add_default_font(float pixel_size)
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
@ -41,8 +72,8 @@ namespace Notifications_Internal{
ImFont* font = io.Fonts->AddFontDefault(&config); ImFont* font = io.Fonts->AddFontDefault(&config);
return font; return font;
} }
*/
static inline void push_style_color(ImGuiCol idx, const ImVec4& col, bool fading_out, float current_fade_opacity) inline void push_style_color(ImGuiCol idx, const ImVec4& col, bool fading_out, float current_fade_opacity)
{ {
if (fading_out) if (fading_out)
ImGui::PushStyleColor(idx, ImVec4(col.x, col.y, col.z, col.w * current_fade_opacity)); ImGui::PushStyleColor(idx, ImVec4(col.x, col.y, col.z, col.w * current_fade_opacity));
@ -184,8 +215,8 @@ void NotificationManager::PopNotification::render(GLCanvas3D& canvas, float init
// color change based on fading out // color change based on fading out
if (m_state == EState::FadingOut) { if (m_state == EState::FadingOut) {
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, ImGui::GetStyleColorVec4(ImGuiCol_WindowBg), true, m_current_fade_opacity); push_style_color(ImGuiCol_WindowBg, ImGui::GetStyleColorVec4(ImGuiCol_WindowBg), true, m_current_fade_opacity);
Notifications_Internal::push_style_color(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_Text), true, m_current_fade_opacity); push_style_color(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_Text), true, m_current_fade_opacity);
fading_pop = true; fading_pop = true;
} }
@ -219,20 +250,20 @@ bool NotificationManager::PopNotification::push_background_color()
{ {
if (m_is_gray) { if (m_is_gray) {
ImVec4 backcolor(0.7f, 0.7f, 0.7f, 0.5f); ImVec4 backcolor(0.7f, 0.7f, 0.7f, 0.5f);
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity); push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity);
return true; return true;
} }
if (m_data.level == NotificationLevel::ErrorNotification) { if (m_data.level == NotificationLevel::ErrorNotification) {
ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg); ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg);
backcolor.x += 0.3f; backcolor.x += 0.3f;
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity); push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity);
return true; return true;
} }
if (m_data.level == NotificationLevel::WarningNotification) { if (m_data.level == NotificationLevel::WarningNotification) {
ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg); ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg);
backcolor.x += 0.3f; backcolor.x += 0.3f;
backcolor.y += 0.15f; backcolor.y += 0.15f;
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity); push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity);
return true; return true;
} }
return false; return false;
@ -259,6 +290,9 @@ void NotificationManager::PopNotification::count_lines()
size_t last_end = 0; size_t last_end = 0;
m_lines_count = 0; m_lines_count = 0;
if (text.empty())
return;
m_endlines.clear(); m_endlines.clear();
while (last_end < text.length() - 1) while (last_end < text.length() - 1)
{ {
@ -283,7 +317,9 @@ void NotificationManager::PopNotification::count_lines()
next_space = text.length(); next_space = text.length();
} }
// when one word longer than line. // when one word longer than line.
if (ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x > m_window_width - m_window_width_offset) { if (ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x > m_window_width - m_window_width_offset ||
ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x < (m_window_width - m_window_width_offset) / 4 * 3
) {
float width_of_a = ImGui::CalcTextSize("a").x; float width_of_a = ImGui::CalcTextSize("a").x;
int letter_count = (int)((m_window_width - m_window_width_offset) / width_of_a); int letter_count = (int)((m_window_width - m_window_width_offset) / width_of_a);
while (last_end + letter_count < text.size() && ImGui::CalcTextSize(text.substr(last_end, letter_count).c_str()).x < m_window_width - m_window_width_offset) { while (last_end + letter_count < text.size() && ImGui::CalcTextSize(text.substr(last_end, letter_count).c_str()).x < m_window_width - m_window_width_offset) {
@ -312,6 +348,9 @@ void NotificationManager::PopNotification::count_lines()
m_lines_count++; m_lines_count++;
} }
} }
// m_text_2 (text after hypertext) is not used for regular notifications right now.
// its caluculation is in HintNotification::count_lines()
} }
void NotificationManager::PopNotification::init() void NotificationManager::PopNotification::init()
@ -339,27 +378,29 @@ void NotificationManager::PopNotification::set_next_window_size(ImGuiWrapper& im
void NotificationManager::PopNotification::render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) void NotificationManager::PopNotification::render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{ {
ImVec2 win_size(win_size_x, win_size_y);
float x_offset = m_left_indentation; float x_offset = m_left_indentation;
std::string fulltext = m_text1 + m_hypertext; //+ m_text2;
ImVec2 text_size = ImGui::CalcTextSize(fulltext.c_str());
// text posistions are calculated by lines count
// large texts has "more" button or are displayed whole
// smaller texts are divided as one liners and two liners
if (m_lines_count > 2) {
if (m_multiline) {
int last_end = 0; int last_end = 0;
float starting_y = m_line_height/2; float starting_y = (m_lines_count == 2 ? win_size_y / 2 - m_line_height : (m_lines_count == 1 ? win_size_y / 2 - m_line_height / 2 : m_line_height / 2));
float shift_y = m_line_height; float shift_y = m_line_height;
std::string line; std::string line;
for (size_t i = 0; i < m_lines_count; i++) { for (size_t i = 0; i < (m_multiline ? m_endlines.size() : std::min(m_endlines.size(), (size_t)2)); i++) {
line.clear(); line.clear();
ImGui::SetCursorPosX(x_offset); ImGui::SetCursorPosX(x_offset);
ImGui::SetCursorPosY(starting_y + i * shift_y); ImGui::SetCursorPosY(starting_y + i * shift_y);
if (m_endlines.size() > i && m_text1.size() >= m_endlines[i]) { if (m_endlines.size() > i && m_text1.size() >= m_endlines[i]) {
if (i == 1 && m_endlines.size() > 2 && !m_multiline) {
// second line with "more" hypertext
line = m_text1.substr(m_endlines[0] + (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0), m_endlines[1] - m_endlines[0] - (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0));
while (ImGui::CalcTextSize(line.c_str()).x > m_window_width - m_window_width_offset - ImGui::CalcTextSize((".." + _u8L("More")).c_str()).x) {
line = line.substr(0, line.length() - 1);
}
line += "..";
}
else {
// regural line
line = m_text1.substr(last_end, m_endlines[i] - last_end); line = m_text1.substr(last_end, m_endlines[i] - last_end);
}
last_end = m_endlines[i]; last_end = m_endlines[i];
if (m_text1.size() > m_endlines[i]) if (m_text1.size() > m_endlines[i])
last_end += (m_text1[m_endlines[i]] == '\n' || m_text1[m_endlines[i]] == ' ' ? 1 : 0); last_end += (m_text1[m_endlines[i]] == '\n' || m_text1[m_endlines[i]] == ' ' ? 1 : 0);
@ -367,77 +408,15 @@ void NotificationManager::PopNotification::render_text(ImGuiWrapper& imgui, cons
} }
} }
//hyperlink text //hyperlink text
if (!m_hypertext.empty()) { if (!m_multiline && m_lines_count > 2) {
render_hypertext(imgui, x_offset + ImGui::CalcTextSize((line + (line.empty() ? "" : " ")).c_str()).x, starting_y + (m_lines_count - 1) * shift_y, m_hypertext); render_hypertext(imgui, x_offset + ImGui::CalcTextSize((line + " ").c_str()).x, starting_y + shift_y, _u8L("More"), true);
}
else if (!m_hypertext.empty()) {
render_hypertext(imgui, x_offset + ImGui::CalcTextSize((line + (line.empty() ? "" : " ")).c_str()).x, starting_y + (m_endlines.size() - 1) * shift_y, m_hypertext);
} }
// text2 (text after hypertext) is not rendered for regular notifications
} else { // its rendering is in HintNotification::render_text
// line1
if (m_text1.size() >= m_endlines[0]) {
ImGui::SetCursorPosX(x_offset);
ImGui::SetCursorPosY(win_size.y / 2 - win_size.y / 6 - m_line_height / 2);
imgui.text(m_text1.substr(0, m_endlines[0]).c_str());
}
// line2
std::string line;
ImGui::SetCursorPosX(x_offset);
ImGui::SetCursorPosY(win_size.y / 2 + win_size.y / 6 - m_line_height / 2);
if (m_text1.size() >= m_endlines[1]) {
line = m_text1.substr(m_endlines[0] + (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0), m_endlines[1] - m_endlines[0] - (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0));
if (ImGui::CalcTextSize(line.c_str()).x > m_window_width - m_window_width_offset - ImGui::CalcTextSize((".." + _u8L("More")).c_str()).x) {
line = line.substr(0, line.length() - 6);
line += "..";
} else
line += " ";
imgui.text(line.c_str());
}
// "More" hypertext
render_hypertext(imgui, x_offset + ImGui::CalcTextSize(line.c_str()).x, win_size.y / 2 + win_size.y / 6 - m_line_height / 2, _u8L("More"), true);
}
} else {
//text 1
float cursor_y = win_size.y / 2 - text_size.y / 2;
float cursor_x = x_offset;
if(m_lines_count > 1) {
// line1
if (m_text1.length() >= m_endlines[0]) { // could be equal than substr takes whole string
ImGui::SetCursorPosX(x_offset);
ImGui::SetCursorPosY(win_size.y / 2 - win_size.y / 6 - m_line_height / 2);
imgui.text(m_text1.substr(0, m_endlines[0]).c_str());
}
// line2
ImGui::SetCursorPosX(x_offset);
cursor_y = win_size.y / 2 + win_size.y / 6 - m_line_height / 2;
ImGui::SetCursorPosY(cursor_y);
if (m_text1.length() > m_endlines[0]) { // must be greater otherwise theres nothing to show and m_text1[m_endlines[0]] is beyond last letter
std::string line = m_text1.substr(m_endlines[0] + (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0));
imgui.text(line.c_str());
cursor_x = x_offset + ImGui::CalcTextSize(line.c_str()).x;
}
} else {
ImGui::SetCursorPosX(x_offset);
ImGui::SetCursorPosY(cursor_y);
imgui.text(m_text1.c_str());
cursor_x = x_offset + ImGui::CalcTextSize(m_text1.c_str()).x;
}
//hyperlink text
if (!m_hypertext.empty()) {
render_hypertext(imgui, cursor_x + 4, cursor_y, m_hypertext);
}
//notification text 2
//text 2 is suposed to be after the hyperlink - currently it is not used
/*
if (!m_text2.empty())
{
ImVec2 part_size = ImGui::CalcTextSize(m_hypertext.c_str());
ImGui::SetCursorPosX(win_size.x / 2 + text_size.x / 2 - part_size.x + 8 - x_offset);
ImGui::SetCursorPosY(cursor_y);
imgui.text(m_text2.c_str());
}
*/
}
} }
void NotificationManager::PopNotification::render_hypertext(ImGuiWrapper& imgui, const float text_x, const float text_y, const std::string text, bool more) void NotificationManager::PopNotification::render_hypertext(ImGuiWrapper& imgui, const float text_x, const float text_y, const std::string text, bool more)
@ -470,7 +449,7 @@ void NotificationManager::PopNotification::render_hypertext(ImGuiWrapper& imgui,
orange_color.y += 0.2f; orange_color.y += 0.2f;
//text //text
Notifications_Internal::push_style_color(ImGuiCol_Text, orange_color, m_state == EState::FadingOut, m_current_fade_opacity); push_style_color(ImGuiCol_Text, orange_color, m_state == EState::FadingOut, m_current_fade_opacity);
ImGui::SetCursorPosX(text_x); ImGui::SetCursorPosX(text_x);
ImGui::SetCursorPosY(text_y); ImGui::SetCursorPosY(text_y);
imgui.text(text.c_str()); imgui.text(text.c_str());
@ -491,8 +470,8 @@ void NotificationManager::PopNotification::render_close_button(ImGuiWrapper& img
ImVec2 win_pos(win_pos_x, win_pos_y); ImVec2 win_pos(win_pos_x, win_pos_y);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f)); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
Notifications_Internal::push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
Notifications_Internal::push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f)); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
@ -542,9 +521,9 @@ void NotificationManager::PopNotification::render_minimize_button(ImGuiWrapper&
{ {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f)); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
Notifications_Internal::push_style_color(ImGuiCol_ButtonActive, ImGui::GetStyleColorVec4(ImGuiCol_WindowBg), m_state == EState::FadingOut, m_current_fade_opacity); push_style_color(ImGuiCol_ButtonActive, ImGui::GetStyleColorVec4(ImGuiCol_WindowBg), m_state == EState::FadingOut, m_current_fade_opacity);
Notifications_Internal::push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
Notifications_Internal::push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
//button - if part if treggered //button - if part if treggered
@ -762,8 +741,8 @@ void NotificationManager::ExportFinishedNotification::render_eject_button(ImGuiW
ImVec2 win_pos(win_pos_x, win_pos_y); ImVec2 win_pos(win_pos_x, win_pos_y);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f)); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
Notifications_Internal::push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
Notifications_Internal::push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f)); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
std::string button_text; std::string button_text;
@ -818,7 +797,7 @@ void NotificationManager::ExportFinishedNotification::render_eject_button(ImGuiW
} }
bool NotificationManager::ExportFinishedNotification::on_text_click() bool NotificationManager::ExportFinishedNotification::on_text_click()
{ {
Notifications_Internal::open_folder(m_export_dir_path); open_folder(m_export_dir_path);
return false; return false;
} }
//------ProgressBar---------------- //------ProgressBar----------------
@ -961,7 +940,7 @@ bool NotificationManager::PrintHostUploadNotification::push_background_color()
if (m_uj_state == UploadJobState::PB_ERROR) { if (m_uj_state == UploadJobState::PB_ERROR) {
ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg); ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg);
backcolor.x += 0.3f; backcolor.x += 0.3f;
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity); push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity);
return true; return true;
} }
return false; return false;
@ -1031,8 +1010,8 @@ void NotificationManager::PrintHostUploadNotification::render_cancel_button(ImGu
ImVec2 win_pos(win_pos_x, win_pos_y); ImVec2 win_pos(win_pos_x, win_pos_y);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f)); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
Notifications_Internal::push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
Notifications_Internal::push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f)); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
std::string button_text; std::string button_text;
@ -1088,10 +1067,10 @@ NotificationManager::NotificationManager(wxEvtHandler* evt_handler) :
} }
void NotificationManager::push_notification(const NotificationType type, int timestamp) void NotificationManager::push_notification(const NotificationType type, int timestamp)
{ {
auto it = std::find_if(basic_notifications.begin(), basic_notifications.end(), auto it = std::find_if(std::begin(basic_notifications), std::end(basic_notifications),
boost::bind(&NotificationData::type, boost::placeholders::_1) == type); boost::bind(&NotificationData::type, boost::placeholders::_1) == type);
assert(it != basic_notifications.end()); assert(it != std::end(basic_notifications));
if (it != basic_notifications.end()) if (it != std::end(basic_notifications))
push_notification_data(*it, timestamp); push_notification_data(*it, timestamp);
} }
void NotificationManager::push_notification(const std::string& text, int timestamp) void NotificationManager::push_notification(const std::string& text, int timestamp)
@ -1331,6 +1310,15 @@ void NotificationManager::upload_job_notification_show_error(int id, const std::
} }
} }
} }
void NotificationManager::push_hint_notification()
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::DidYouKnowHint)
return;
}
NotificationData data{ NotificationType::DidYouKnowHint, NotificationLevel::RegularNotification, 0, "" };
push_notification_data(std::make_unique<NotificationManager::HintNotification>(data, m_id_provider, m_evt_handler), 0);
}
bool NotificationManager::push_notification_data(const NotificationData& notification_data, int timestamp) bool NotificationManager::push_notification_data(const NotificationData& notification_data, int timestamp)
{ {
return push_notification_data(std::make_unique<PopNotification>(notification_data, m_id_provider, m_evt_handler), timestamp); return push_notification_data(std::make_unique<PopNotification>(notification_data, m_id_provider, m_evt_handler), timestamp);

View File

@ -89,8 +89,9 @@ enum class NotificationType
UndoDesktopIntegrationSuccess, UndoDesktopIntegrationSuccess,
UndoDesktopIntegrationFail, UndoDesktopIntegrationFail,
// Notification that a printer has more extruders than are supported by MM Gizmo/segmentation. // Notification that a printer has more extruders than are supported by MM Gizmo/segmentation.
MmSegmentationExceededExtrudersLimit MmSegmentationExceededExtrudersLimit,
// Did you know Notification appearing on startup with arrows to change hint
DidYouKnowHint
}; };
class NotificationManager class NotificationManager
@ -160,6 +161,8 @@ public:
void set_upload_job_notification_percentage(int id, const std::string& filename, const std::string& host, float percentage); void set_upload_job_notification_percentage(int id, const std::string& filename, const std::string& host, float percentage);
void upload_job_notification_show_canceled(int id, const std::string& filename, const std::string& host); void upload_job_notification_show_canceled(int id, const std::string& filename, const std::string& host);
void upload_job_notification_show_error(int id, const std::string& filename, const std::string& host); void upload_job_notification_show_error(int id, const std::string& filename, const std::string& host);
// Hint (did you know) notification
void push_hint_notification();
// Close old notification ExportFinished. // Close old notification ExportFinished.
void new_export_began(bool on_removable); void new_export_began(bool on_removable);
// finds ExportFinished notification and closes it if it was to removable device // finds ExportFinished notification and closes it if it was to removable device
@ -188,7 +191,7 @@ private:
// Callback for hypertext - returns true if notification should close after triggering // Callback for hypertext - returns true if notification should close after triggering
// Usually sends event to UI thread thru wxEvtHandler. // Usually sends event to UI thread thru wxEvtHandler.
// Examples in basic_notifications. // Examples in basic_notifications.
std::function<bool(wxEvtHandler*)> callback { nullptr }; std::function<bool(wxEvtHandler*)> callback;
const std::string text2; const std::string text2;
}; };
@ -237,7 +240,7 @@ private:
//returns top in actual frame //returns top in actual frame
float get_current_top() const { return m_top_y; } float get_current_top() const { return m_top_y; }
const NotificationType get_type() const { return m_data.type; } const NotificationType get_type() const { return m_data.type; }
const NotificationData get_data() const { return m_data; } const NotificationData& get_data() const { return m_data; }
const bool is_gray() const { return m_is_gray; } const bool is_gray() const { return m_is_gray; }
void set_gray(bool g) { m_is_gray = g; } void set_gray(bool g) { m_is_gray = g; }
virtual bool compare_text(const std::string& text) const; virtual bool compare_text(const std::string& text) const;
@ -318,7 +321,10 @@ private:
float m_top_y { 0.0f }; float m_top_y { 0.0f };
// Height of text - Used as basic scaling unit! // Height of text - Used as basic scaling unit!
float m_line_height; float m_line_height;
// endlines for text1, hypertext excluded
std::vector<size_t> m_endlines; std::vector<size_t> m_endlines;
// endlines for text2
std::vector<size_t> m_endlines2;
// Gray are f.e. eorrors when its uknown if they are still valid // Gray are f.e. eorrors when its uknown if they are still valid
bool m_is_gray { false }; bool m_is_gray { false };
//if multiline = true, notification is showing all lines(>2) //if multiline = true, notification is showing all lines(>2)
@ -337,7 +343,7 @@ private:
void set_large(bool l); void set_large(bool l);
bool get_large() { return m_is_large; } bool get_large() { return m_is_large; }
void set_print_info(const std::string &info); void set_print_info(const std::string &info);
virtual void render(GLCanvas3D& canvas, float initial_y, bool move_from_overlay, float overlay_width) override void render(GLCanvas3D& canvas, float initial_y, bool move_from_overlay, float overlay_width) override
{ {
// This notification is always hidden if !large (means side bar is collapsed) // This notification is always hidden if !large (means side bar is collapsed)
if (!get_large() && !is_finished()) if (!get_large() && !is_finished())
@ -345,7 +351,7 @@ private:
PopNotification::render(canvas, initial_y, move_from_overlay, overlay_width); PopNotification::render(canvas, initial_y, move_from_overlay, overlay_width);
} }
protected: protected:
virtual void render_text(ImGuiWrapper& imgui, void render_text(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y, const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y) const float win_pos_x, const float win_pos_y)
override; override;
@ -366,7 +372,7 @@ private:
{ {
public: public:
PlaterWarningNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler) : PopNotification(n, id_provider, evt_handler) {} PlaterWarningNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler) : PopNotification(n, id_provider, evt_handler) {}
virtual void close() override { if(is_finished()) return; m_state = EState::Hidden; wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); } void close() override { if(is_finished()) return; m_state = EState::Hidden; wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); }
void real_close() { m_state = EState::ClosePending; wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); } void real_close() { m_state = EState::ClosePending; wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); }
void show() { m_state = EState::Unknown; } void show() { m_state = EState::Unknown; }
}; };
@ -392,7 +398,7 @@ private:
const float win_size_x, const float win_size_y, const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y) const float win_pos_x, const float win_pos_y)
{} {}
virtual void render_minimize_button(ImGuiWrapper& imgui, void render_minimize_button(ImGuiWrapper& imgui,
const float win_pos_x, const float win_pos_y) override {} const float win_pos_x, const float win_pos_y) override {}
float m_percentage; float m_percentage;
@ -421,22 +427,22 @@ private:
m_has_cancel_button = true; m_has_cancel_button = true;
} }
static std::string get_upload_job_text(int id, const std::string& filename, const std::string& host) { return /*"[" + std::to_string(id) + "] " + */filename + " -> " + host; } static std::string get_upload_job_text(int id, const std::string& filename, const std::string& host) { return /*"[" + std::to_string(id) + "] " + */filename + " -> " + host; }
virtual void set_percentage(float percent) override; void set_percentage(float percent) override;
void cancel() { m_uj_state = UploadJobState::PB_CANCELLED; m_has_cancel_button = false; } void cancel() { m_uj_state = UploadJobState::PB_CANCELLED; m_has_cancel_button = false; }
void error() { m_uj_state = UploadJobState::PB_ERROR; m_has_cancel_button = false; init(); } void error() { m_uj_state = UploadJobState::PB_ERROR; m_has_cancel_button = false; init(); }
bool compare_job_id(const int other_id) const { return m_job_id == other_id; } bool compare_job_id(const int other_id) const { return m_job_id == other_id; }
virtual bool compare_text(const std::string& text) const override { return false; } bool compare_text(const std::string& text) const override { return false; }
protected: protected:
virtual void init() override; void init() override;
virtual void count_spaces() override; void count_spaces() override;
virtual bool push_background_color() override; bool push_background_color() override;
virtual void render_bar(ImGuiWrapper& imgui, void render_bar(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y, const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y) override; const float win_pos_x, const float win_pos_y) override;
virtual void render_cancel_button(ImGuiWrapper& imgui, void render_cancel_button(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y, const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y) override; const float win_pos_x, const float win_pos_y) override;
virtual void render_left_sign(ImGuiWrapper& imgui) override; void render_left_sign(ImGuiWrapper& imgui) override;
// Identifies job in cancel callback // Identifies job in cancel callback
int m_job_id; int m_job_id;
// Size of uploaded size to be displayed in MB // Size of uploaded size to be displayed in MB
@ -461,24 +467,27 @@ private:
std::string m_export_dir_path; std::string m_export_dir_path;
protected: protected:
// Reserves space on right for more buttons // Reserves space on right for more buttons
virtual void count_spaces() override; void count_spaces() override;
virtual void render_text(ImGuiWrapper& imgui, void render_text(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y, const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y) override; const float win_pos_x, const float win_pos_y) override;
// Renders also button to open directory with exported path and eject removable media // Renders also button to open directory with exported path and eject removable media
virtual void render_close_button(ImGuiWrapper& imgui, void render_close_button(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y, const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y) override; const float win_pos_x, const float win_pos_y) override;
void render_eject_button(ImGuiWrapper& imgui, void render_eject_button(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y, const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y); const float win_pos_x, const float win_pos_y);
virtual void render_minimize_button(ImGuiWrapper& imgui, const float win_pos_x, const float win_pos_y) override void render_minimize_button(ImGuiWrapper& imgui, const float win_pos_x, const float win_pos_y) override
{ m_minimize_b_visible = false; } { m_minimize_b_visible = false; }
virtual bool on_text_click() override; bool on_text_click() override;
// local time of last hover for showing tooltip // local time of last hover for showing tooltip
long m_hover_time { 0 }; long m_hover_time { 0 };
}; };
// in HintNotification.hpp
class HintNotification;
//pushes notification into the queue of notifications that are rendered //pushes notification into the queue of notifications that are rendered
//can be used to create custom notification //can be used to create custom notification
bool push_notification_data(const NotificationData& notification_data, int timestamp); bool push_notification_data(const NotificationData& notification_data, int timestamp);
@ -506,34 +515,7 @@ private:
// Notification types that can be shown multiple types at once (compared by text) // Notification types that can be shown multiple types at once (compared by text)
const std::vector<NotificationType> m_multiple_types = { NotificationType::CustomNotification, NotificationType::PlaterWarning, NotificationType::ProgressBar, NotificationType::PrintHostUpload }; const std::vector<NotificationType> m_multiple_types = { NotificationType::CustomNotification, NotificationType::PlaterWarning, NotificationType::ProgressBar, NotificationType::PrintHostUpload };
//prepared (basic) notifications //prepared (basic) notifications
const std::vector<NotificationData> basic_notifications = { static const NotificationData basic_notifications[];
{NotificationType::Mouse3dDisconnected, NotificationLevel::RegularNotification, 10, _u8L("3D Mouse disconnected.") },
{NotificationType::PresetUpdateAvailable, NotificationLevel::ImportantNotification, 20, _u8L("Configuration update is available."), _u8L("See more."),
[](wxEvtHandler* evnthndlr) {
if (evnthndlr != nullptr)
wxPostEvent(evnthndlr, PresetUpdateAvailableClickedEvent(EVT_PRESET_UPDATE_AVAILABLE_CLICKED));
return true;
}
},
{NotificationType::NewAppAvailable, NotificationLevel::ImportantNotification, 20, _u8L("New version is available."), _u8L("See Releases page."), [](wxEvtHandler* evnthndlr){
wxLaunchDefaultBrowser("https://github.com/prusa3d/PrusaSlicer/releases"); return true; }},
{NotificationType::EmptyColorChangeCode, NotificationLevel::RegularNotification, 10,
_u8L("You have just added a G-code for color change, but its value is empty.\n"
"To export the G-code correctly, check the \"Color Change G-code\" in \"Printer Settings > Custom G-code\"") },
{NotificationType::EmptyAutoColorChange, NotificationLevel::RegularNotification, 10,
_u8L("This model doesn't allow to automatically add the color changes") },
{NotificationType::DesktopIntegrationSuccess, NotificationLevel::RegularNotification, 10,
_u8L("Desktop integration was successful.") },
{NotificationType::DesktopIntegrationFail, NotificationLevel::WarningNotification, 10,
_u8L("Desktop integration failed.") },
{NotificationType::UndoDesktopIntegrationSuccess, NotificationLevel::RegularNotification, 10,
_u8L("Undo desktop integration was successful.") },
{NotificationType::UndoDesktopIntegrationFail, NotificationLevel::WarningNotification, 10,
_u8L("Undo desktop integration failed.") },
//{NotificationType::NewAppAvailable, NotificationLevel::ImportantNotification, 20, _u8L("New vesion of PrusaSlicer is available.", _u8L("Download page.") },
//{NotificationType::LoadingFailed, NotificationLevel::RegularNotification, 20, _u8L("Loading of model has Failed") },
//{NotificationType::DeviceEjected, NotificationLevel::RegularNotification, 10, _u8L("Removable device has been safely ejected")} // if we want changeble text (like here name of device), we need to do it as CustomNotification
};
}; };
}//namespace GUI }//namespace GUI

View File

@ -1045,6 +1045,12 @@ void Sidebar::search()
p->searcher.search(); p->searcher.search();
} }
void Sidebar::jump_to_option(const std::string& opt_key, Preset::Type type, const std::wstring& category)
{
//const Search::Option& opt = p->searcher.get_option(opt_key, type);
wxGetApp().get_tab(type)->activate_option(opt_key, category);
}
void Sidebar::jump_to_option(size_t selected) void Sidebar::jump_to_option(size_t selected)
{ {
const Search::Option& opt = p->searcher.get_option(selected); const Search::Option& opt = p->searcher.get_option(selected);

View File

@ -83,6 +83,7 @@ public:
void sys_color_changed(); void sys_color_changed();
void search(); void search();
void jump_to_option(size_t selected); void jump_to_option(size_t selected);
void jump_to_option(const std::string& opt_key, Preset::Type type, const std::wstring& category);
ObjectManipulation* obj_manipul(); ObjectManipulation* obj_manipul();
ObjectList* obj_list(); ObjectList* obj_list();

View File

@ -11,14 +11,14 @@
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
PreferencesDialog::PreferencesDialog(wxWindow* parent) : PreferencesDialog::PreferencesDialog(wxWindow* parent, int selected_tab) :
DPIDialog(parent, wxID_ANY, _L("Preferences"), wxDefaultPosition, DPIDialog(parent, wxID_ANY, _L("Preferences"), wxDefaultPosition,
wxDefaultSize, wxDEFAULT_DIALOG_STYLE) wxDefaultSize, wxDEFAULT_DIALOG_STYLE)
{ {
#ifdef __WXOSX__ #ifdef __WXOSX__
isOSX = true; isOSX = true;
#endif #endif
build(); build(selected_tab);
} }
static std::shared_ptr<ConfigOptionsGroup>create_options_tab(const wxString& title, wxBookCtrlBase* tabs) static std::shared_ptr<ConfigOptionsGroup>create_options_tab(const wxString& title, wxBookCtrlBase* tabs)
@ -44,7 +44,7 @@ static void activate_options_tab(std::shared_ptr<ConfigOptionsGroup> optgroup)
sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10); sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10);
} }
void PreferencesDialog::build() void PreferencesDialog::build(size_t selected_tab)
{ {
#ifdef _WIN32 #ifdef _WIN32
wxGetApp().UpdateDarkUI(this); wxGetApp().UpdateDarkUI(this);
@ -350,6 +350,13 @@ void PreferencesDialog::build()
m_optgroup_gui->append_single_option_line(option); m_optgroup_gui->append_single_option_line(option);
#endif #endif
def.label = L("Show \"Did you know\" hints after start");
def.type = coBool;
def.tooltip = L("If enabled, useful hints are displayed at startup.");
def.set_default_value(new ConfigOptionBool{ app_config->get("show_hints") == "1" });
option = Option(def, "show_hints");
m_optgroup_gui->append_single_option_line(option);
def.label = L("Use custom size for toolbar icons"); def.label = L("Use custom size for toolbar icons");
def.type = coBool; def.type = coBool;
def.tooltip = L("If enabled, you can change size of toolbar icons manually."); def.tooltip = L("If enabled, you can change size of toolbar icons manually.");
@ -387,6 +394,9 @@ void PreferencesDialog::build()
} }
#endif // ENABLE_ENVIRONMENT_MAP #endif // ENABLE_ENVIRONMENT_MAP
if (selected_tab < tabs->GetPageCount())
tabs->SetSelection(selected_tab);
auto sizer = new wxBoxSizer(wxVERTICAL); auto sizer = new wxBoxSizer(wxVERTICAL);
sizer->Add(tabs, 1, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 5); sizer->Add(tabs, 1, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 5);

View File

@ -33,14 +33,14 @@ class PreferencesDialog : public DPIDialog
bool m_recreate_GUI{false}; bool m_recreate_GUI{false};
public: public:
explicit PreferencesDialog(wxWindow* parent); explicit PreferencesDialog(wxWindow* parent, int selected_tab = 0);
~PreferencesDialog() = default; ~PreferencesDialog() = default;
bool settings_layout_changed() const { return m_settings_layout_changed; } bool settings_layout_changed() const { return m_settings_layout_changed; }
bool seq_top_layer_only_changed() const { return m_seq_top_layer_only_changed; } bool seq_top_layer_only_changed() const { return m_seq_top_layer_only_changed; }
bool seq_seq_top_gcode_indices_changed() const { return m_seq_top_gcode_indices_changed; } bool seq_seq_top_gcode_indices_changed() const { return m_seq_top_gcode_indices_changed; }
bool recreate_GUI() const { return m_recreate_GUI; } bool recreate_GUI() const { return m_recreate_GUI; }
void build(); void build(size_t selected_tab = 0);
void accept(wxEvent&); void accept(wxEvent&);
protected: protected: