From dc52e58e65ca04f0a00d16178e08e17fd018836c Mon Sep 17 00:00:00 2001 From: dustinhartlyn <79132671+dustinhartlyn@users.noreply.github.com> Date: Tue, 30 Mar 2021 22:05:59 -0700 Subject: [PATCH 1/7] minor fix open/save dialogue on windows On windows 10 the open/save dialogue box has an minor error, and I believe I fixed it. When "Open" is selected from the menu, the title of the dialogue box says "SolveSpace - Save File" and the entered file name is "united". My fix correctly titles the dialoged box, and leaves the address bar blank when a file is being opened because "united" is only needed as a default name when a file being saved. I found that class FileDialogImplWin32 from guiwin.cpp contains two if statements for "isSaveDialog". This is redundant. I removed the first where the title was originally set, but not working. I then set the title in the second if statement and moved the 'if isEmpty'' to this section. --- src/platform/guiwin.cpp | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/platform/guiwin.cpp b/src/platform/guiwin.cpp index d88519589..47700b3cd 100644 --- a/src/platform/guiwin.cpp +++ b/src/platform/guiwin.cpp @@ -1569,11 +1569,6 @@ class FileDialogImplWin32 final : public FileDialog { ofn.nMaxFile = sizeof(filenameWC) / sizeof(wchar_t); ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; - if(isSaveDialog) { - SetTitle(C_("title", "Save File")); - } else { - SetTitle(C_("title", "Open File")); - } } void SetTitle(std::string title) override { @@ -1626,15 +1621,16 @@ class FileDialogImplWin32 final : public FileDialog { } bool RunModal() override { - if(GetFilename().IsEmpty()) { - SetFilename(Path::From(_("untitled"))); - } - - if(isSaveDialog) { - return GetSaveFileNameW(&ofn) == TRUE; - } else { - return GetOpenFileNameW(&ofn) == TRUE; - } + if(isSaveDialog) { + SetTitle(C_("title", "Save File")); + if(GetFilename().IsEmpty()) { + SetFilename(Path::From(_("untitled"))); + } + return GetSaveFileNameW(&ofn) == TRUE; + } else { + SetTitle(C_("title", "Open File")); + return GetOpenFileNameW(&ofn) == TRUE; + } } }; From e369173cf5c07ed05d3b47830890f8a838239530 Mon Sep 17 00:00:00 2001 From: dustinhartlyn <79132671+dustinhartlyn@users.noreply.github.com> Date: Wed, 31 Mar 2021 18:40:31 -0700 Subject: [PATCH 2/7] Update guiwin.cpp replaced tabs with spaces --- src/platform/guiwin.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/platform/guiwin.cpp b/src/platform/guiwin.cpp index 47700b3cd..c38a91c7c 100644 --- a/src/platform/guiwin.cpp +++ b/src/platform/guiwin.cpp @@ -1621,16 +1621,16 @@ class FileDialogImplWin32 final : public FileDialog { } bool RunModal() override { - if(isSaveDialog) { - SetTitle(C_("title", "Save File")); - if(GetFilename().IsEmpty()) { - SetFilename(Path::From(_("untitled"))); - } - return GetSaveFileNameW(&ofn) == TRUE; - } else { - SetTitle(C_("title", "Open File")); - return GetOpenFileNameW(&ofn) == TRUE; - } + if(isSaveDialog) { + SetTitle(C_("title", "Save File")); + if(GetFilename().IsEmpty()) { + SetFilename(Path::From(_("untitled"))); + } + return GetSaveFileNameW(&ofn) == TRUE; + } else { + SetTitle(C_("title", "Open File")); + return GetOpenFileNameW(&ofn) == TRUE; + } } }; From 3c74b832ba840e557a8a90379bbbcdcc9d0149c4 Mon Sep 17 00:00:00 2001 From: Dustin Hartlyn Date: Sun, 20 Feb 2022 15:19:47 -0800 Subject: [PATCH 3/7] Created ZoomToMouse function in graphicswin.cpp which referances the mouse position directly. Simplified MouseScroll in mouse.cpp to point to this function instead of altering zoom directly. Also pointed zoom commpand from keyboard and menu to ZoomToMouse so that it works avoids different behavior. --- src/graphicswin.cpp | 39 +++++++++++++++++++++++++++++++++++---- src/mouse.cpp | 35 ++++++++--------------------------- src/ui.h | 3 ++- 3 files changed, 45 insertions(+), 32 deletions(-) diff --git a/src/graphicswin.cpp b/src/graphicswin.cpp index c7c74d98b..98ed54d68 100644 --- a/src/graphicswin.cpp +++ b/src/graphicswin.cpp @@ -712,16 +712,47 @@ double GraphicsWindow::ZoomToFit(const Camera &camera, return scale; } + +void GraphicsWindow::ZoomToMouse(double zoomMultiplyer) { + double offsetRight = offset.Dot(projRight); + double offsetUp = offset.Dot(projUp); + + double width, height; + window->GetContentSize(&width, &height); + + double righti = currentMousePosition.x / scale - offsetRight; + double upi = currentMousePosition.y / scale - offsetUp; + + // zoomMultiplyer of 1 gives a default zoom factor of 1.2x: zoomMultiplyer * 1.2 + // zoom = adjusted zoom negative zoomMultiplyer will zoom out, positive will zoom in + // + + scale *= exp(0.1823216 * zoomMultiplyer); // ln(1.2) = 0.1823216 + + double rightf = currentMousePosition.x / scale - offsetRight; + double upf = currentMousePosition.y / scale - offsetUp; + + offset = offset.Plus(projRight.ScaledBy(rightf - righti)); + offset = offset.Plus(projUp.ScaledBy(upf - upi)); + + if(SS.TW.shown.screen == TextWindow::Screen::EDIT_VIEW) { + if(havePainted) { + SS.ScheduleShowTW(); + } + } + havePainted = false; + Invalidate(); +} + + void GraphicsWindow::MenuView(Command id) { switch(id) { case Command::ZOOM_IN: - SS.GW.scale *= 1.2; - SS.ScheduleShowTW(); + SS.GW.ZoomToMouse(1); break; case Command::ZOOM_OUT: - SS.GW.scale /= 1.2; - SS.ScheduleShowTW(); + SS.GW.ZoomToMouse(-1); break; case Command::ZOOM_TO_FIT: diff --git a/src/mouse.cpp b/src/mouse.cpp index 5e7cde269..a0e501c14 100644 --- a/src/mouse.cpp +++ b/src/mouse.cpp @@ -88,7 +88,6 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown, { if(window->IsEditorVisible()) return; if(context.active) return; - SS.extraLine.draw = false; if(!orig.mouseDown) { @@ -879,6 +878,9 @@ bool GraphicsWindow::MouseEvent(Platform::MouseEvent event) { event.x = event.x - width / 2; event.y = height / 2 - event.y; + // orig.mouse.x = event.x; // provents secont point for shapes + // orig.mouse.y = event.y; + switch(event.type) { case MouseEvent::Type::MOTION: @@ -914,7 +916,7 @@ bool GraphicsWindow::MouseEvent(Platform::MouseEvent event) { break; case MouseEvent::Type::SCROLL_VERT: - this->MouseScroll(event.x, event.y, event.shiftDown ? event.scrollDelta / 10 : event.scrollDelta); + this->MouseScroll(event.shiftDown ? event.scrollDelta / 10 : event.scrollDelta); break; case MouseEvent::Type::LEAVE: @@ -1301,7 +1303,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my, bool shiftDown, bool ct if(g != NULL) { g->visible = true; } - + //dbp(orig.mouse); // debug output SS.ScheduleShowTW(); Invalidate(); } @@ -1478,17 +1480,10 @@ void GraphicsWindow::EditControlDone(const std::string &s) { } } -void GraphicsWindow::MouseScroll(double x, double y, double delta) { - double offsetRight = offset.Dot(projRight); - double offsetUp = offset.Dot(projUp); - - double righti = x/scale - offsetRight; - double upi = y/scale - offsetUp; - - // The default zoom factor is 1.2x for one scroll wheel click (delta==1). +void GraphicsWindow::MouseScroll(double zoomMultiplyer) { // To support smooth scrolling where scroll wheel events come in increments // smaller (or larger) than 1 we do: - // scale *= exp(ln(1.2) * delta); + // scale *= exp(ln(1.2) * zoomMultiplyer); // to ensure that the same total scroll delta always results in the same // total zoom irrespective of in how many increments the zoom was applied. // For example if we scroll a total delta of a+b in two events vs. one then @@ -1496,21 +1491,7 @@ void GraphicsWindow::MouseScroll(double x, double y, double delta) { // while // scale * a * b != scale * (a+b) // So this constant is ln(1.2) = 0.1823216 to make the default zoom 1.2x - scale *= exp(0.1823216 * delta); - - double rightf = x/scale - offsetRight; - double upf = y/scale - offsetUp; - - offset = offset.Plus(projRight.ScaledBy(rightf - righti)); - offset = offset.Plus(projUp.ScaledBy(upf - upi)); - - if(SS.TW.shown.screen == TextWindow::Screen::EDIT_VIEW) { - if(havePainted) { - SS.ScheduleShowTW(); - } - } - havePainted = false; - Invalidate(); + ZoomToMouse(zoomMultiplyer); } void GraphicsWindow::MouseLeave() { diff --git a/src/ui.h b/src/ui.h index 0d121b64f..c4ffff2ba 100644 --- a/src/ui.h +++ b/src/ui.h @@ -622,6 +622,7 @@ class GraphicsWindow { void HandlePointForZoomToFit(Vector p, Point2d *pmax, Point2d *pmin, double *wmin, bool usePerspective, const Camera &camera); + void ZoomToMouse(double delta); void LoopOverPoints(const std::vector &entities, const std::vector &constraints, const std::vector &faces, @@ -842,7 +843,7 @@ class GraphicsWindow { void MouseLeftDoubleClick(double x, double y); void MouseMiddleOrRightDown(double x, double y); void MouseRightUp(double x, double y); - void MouseScroll(double x, double y, double delta); + void MouseScroll(double delta); void MouseLeave(); bool KeyboardEvent(Platform::KeyboardEvent event); void EditControlDone(const std::string &s); From 3a424fbb020dfbdc9db91a82af0bc74f614b75f7 Mon Sep 17 00:00:00 2001 From: Dustin Hartlyn Date: Sun, 20 Feb 2022 15:45:49 -0800 Subject: [PATCH 4/7] clean up some comments --- src/mouse.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/mouse.cpp b/src/mouse.cpp index a0e501c14..d183f58a0 100644 --- a/src/mouse.cpp +++ b/src/mouse.cpp @@ -88,6 +88,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown, { if(window->IsEditorVisible()) return; if(context.active) return; + SS.extraLine.draw = false; if(!orig.mouseDown) { @@ -878,9 +879,6 @@ bool GraphicsWindow::MouseEvent(Platform::MouseEvent event) { event.x = event.x - width / 2; event.y = height / 2 - event.y; - // orig.mouse.x = event.x; // provents secont point for shapes - // orig.mouse.y = event.y; - switch(event.type) { case MouseEvent::Type::MOTION: @@ -1303,7 +1301,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my, bool shiftDown, bool ct if(g != NULL) { g->visible = true; } - //dbp(orig.mouse); // debug output + SS.ScheduleShowTW(); Invalidate(); } From 9cbe27079a91e50ed16d37f15b802d07b5e8084c Mon Sep 17 00:00:00 2001 From: Dustin Hartlyn Date: Sat, 5 Mar 2022 23:05:02 -0800 Subject: [PATCH 5/7] Change: Tools menu specifies which tools reactivate after use. Adition: Menu option (linked to spacebar) which alternates between last selected tool and mouse. --- src/graphicswin.cpp | 21 +++++-- src/mouse.cpp | 47 ++++++++++++++-- src/toolbar.cpp | 130 +++++++++++++++++++------------------------- src/ui.h | 9 ++- 4 files changed, 123 insertions(+), 84 deletions(-) diff --git a/src/graphicswin.cpp b/src/graphicswin.cpp index 98ed54d68..7901c4cf1 100644 --- a/src/graphicswin.cpp +++ b/src/graphicswin.cpp @@ -37,7 +37,7 @@ struct MenuEntry { #define KC MenuKind::CHECK_MARK #define KR MenuKind::RADIO_MARK const MenuEntry Menu[] = { -//lv label cmd accel kind +//lv label cmd accel kind *fn { 0, N_("&File"), Command::NONE, 0, KN, NULL }, { 1, N_("&New"), Command::NEW, C|'n', KN, mFile }, { 1, N_("&Open..."), Command::OPEN, C|'o', KN, mFile }, @@ -60,7 +60,8 @@ const MenuEntry Menu[] = { { 0, N_("&Edit"), Command::NONE, 0, KN, NULL }, { 1, N_("&Undo"), Command::UNDO, C|'z', KN, mEdit }, { 1, N_("&Redo"), Command::REDO, C|'y', KN, mEdit }, -{ 1, N_("Re&generate All"), Command::REGEN_ALL, ' ', KN, mEdit }, +{ 1, N_("Re&generate All"), Command::REGEN_ALL, C|'r', KN, mEdit }, + { 1, NULL, Command::NONE, 0, KN, NULL }, { 1, N_("Snap Selection to &Grid"), Command::SNAP_TO_GRID, '.', KN, mEdit }, { 1, N_("Rotate Imported &90°"), Command::ROTATE_90, '9', KN, mEdit }, @@ -141,6 +142,8 @@ const MenuEntry Menu[] = { { 1, N_("To&ggle Construction"), Command::CONSTRUCTION, 'g', KN, mReq }, { 1, N_("Tangent &Arc at Point"), Command::TANGENT_ARC, S|'a', KN, mReq }, { 1, N_("Split Curves at &Intersection"), Command::SPLIT_CURVES, 'i', KN, mReq }, +{ 1, N_("Other Tools"), Command::NONE, 0, KN, NULL }, +{ 2, N_("Alternate Tool"), Command::ALTERNATE_TOOL, ' ', KN, mEdit }, { 0, N_("&Constrain"), Command::NONE, 0, KN, mCon }, { 1, N_("&Distance / Diameter"), Command::DISTANCE_DIA, 'd', KN, mCon }, @@ -1109,6 +1112,11 @@ void GraphicsWindow::MenuEdit(Command id) { SS.GW.persistentDirty = true; break; + // this is the space bar alternative tool menu - switch between the most recent tool and mouse + case Command::ALTERNATE_TOOL: + SS.GW.AlternateTool(); + break; + case Command::SELECT_ALL: { for(Entity &e : SK.entity) { if(e.group != SS.GW.activeGroup) continue; @@ -1350,8 +1358,9 @@ void GraphicsWindow::MenuRequest(Command id) { } s = _("click top left of image"); goto c; c: + //SS.GW.activeTool = id; SS.GW.pending.operation = GraphicsWindow::Pending::COMMAND; - SS.GW.pending.command = id; + SS.GW.pending.command = id; SS.GW.pending.description = s; SS.ScheduleShowTW(); SS.GW.Invalidate(); // repaint toolbar @@ -1397,11 +1406,15 @@ void GraphicsWindow::MenuRequest(Command id) { default: ssassert(false, "Unexpected menu ID"); } + // If tool can be used multiple times, mark as active. + if(SS.GW.CheckIfKeepCommandActive(SS.GW.pending.command)) { + SS.GW.activeTool = id;//SS.GW.pending.operation; + } } void GraphicsWindow::ClearSuper() { if(window) window->HideEditor(); - ClearPending(); + ClearPending(true); ClearSelection(); hover.Clear(); EnsureValidActives(); diff --git a/src/mouse.cpp b/src/mouse.cpp index d183f58a0..b5961687e 100644 --- a/src/mouse.cpp +++ b/src/mouse.cpp @@ -467,15 +467,51 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown, } } -void GraphicsWindow::ClearPending(bool scheduleShowTW) { +void GraphicsWindow::AlternateTool() { +// Switches between most recent tool and the mouse selector + if(SS.GW.activeTool != Command::NONE) { + if(pending.command == Command::NONE) { + ClearPending(true, false); + MenuRequest(SS.GW.activeTool); + // rechose tool through menu? + } else ClearPending(true, false); + SS.GW.Invalidate(); + SS.ScheduleShowTW(); + } +} + +void GraphicsWindow::ClearPending(bool scheduleShowTW, bool allowCommandToContinue) { +// Clears selected tool or, steps of a tool's use (tow point rectangle). +// Allows tool to be reactivated after use if specified in toolbar.cpp/Toolbar[] + Command temp_store = Command::NONE; pending.points.Clear(); pending.requests.Clear(); - pending = {}; + + if(pending.command != Command::NONE && allowCommandToContinue) { + + if(CheckIfKeepCommandActive(pending.command)) { + temp_store = pending.command; + }; + pending = {}; + pending.stored_command = temp_store; + // If there is a tool stored, activate it + } else if(pending.stored_command != Command::NONE && allowCommandToContinue) { + temp_store = pending.stored_command; + pending = {}; + if(allowCommandToContinue) { + pending.command = temp_store; + pending.operation = Pending::COMMAND; + } + } else { + pending = {}; + } + if(scheduleShowTW) { SS.ScheduleShowTW(); } } + bool GraphicsWindow::IsFromPending(hRequest r) { for(auto &req : pending.requests) { if(req == r) return true; @@ -794,6 +830,7 @@ void GraphicsWindow::MouseRightUp(double x, double y) { hRequest GraphicsWindow::AddRequest(Request::Type type) { return AddRequest(type, /*rememberForUndo=*/true); } + hRequest GraphicsWindow::AddRequest(Request::Type type, bool rememberForUndo) { if(rememberForUndo) SS.UndoRemember(); @@ -1021,7 +1058,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my, bool shiftDown, bool ct } } - pending.operation = Pending::DRAGGING_NEW_POINT; + pending.operation = Pending::DRAGGING_NEW_POINT; pending.point = lns[1].entity(2); pending.description = _("click to place other corner of rectangle"); hr = lns[0]; @@ -1164,13 +1201,15 @@ void GraphicsWindow::MouseLeftDown(double mx, double my, bool shiftDown, bool ct break; case Pending::DRAGGING_RADIUS: - ClearPending(); + //ClearPending(); break; case Pending::DRAGGING_NEW_POINT: case Pending::DRAGGING_NEW_ARC_POINT: ConstrainPointByHovered(pending.point, &mouse); ClearPending(); + //pending.command = Command::RECTANGLE; + //pending.operation = Pending::COMMAND; break; case Pending::DRAGGING_NEW_CUBIC_POINT: { diff --git a/src/toolbar.cpp b/src/toolbar.cpp index 74764883a..6bd4c38a3 100644 --- a/src/toolbar.cpp +++ b/src/toolbar.cpp @@ -10,86 +10,68 @@ struct ToolIcon { std::string name; Command command; + bool keep_active; const char *tooltip; std::shared_ptr pixmap; }; static ToolIcon Toolbar[] = { - { "line", Command::LINE_SEGMENT, - N_("Sketch line segment"), {} }, - { "rectangle", Command::RECTANGLE, - N_("Sketch rectangle"), {} }, - { "circle", Command::CIRCLE, - N_("Sketch circle"), {} }, - { "arc", Command::ARC, - N_("Sketch arc of a circle"), {} }, - { "text", Command::TTF_TEXT, - N_("Sketch curves from text in a TrueType font"), {} }, - { "image", Command::IMAGE, - N_("Sketch image from a file"), {} }, - { "tangent-arc", Command::TANGENT_ARC, - N_("Create tangent arc at selected point"), {} }, - { "bezier", Command::CUBIC, - N_("Sketch cubic Bezier spline"), {} }, - { "point", Command::DATUM_POINT, - N_("Sketch datum point"), {} }, - { "construction", Command::CONSTRUCTION, - N_("Toggle construction"), {} }, - { "trim", Command::SPLIT_CURVES, - N_("Split lines / curves where they intersect"), {} }, - { "", Command::NONE, "", {} }, - - { "length", Command::DISTANCE_DIA, - N_("Constrain distance / diameter / length"), {} }, - { "angle", Command::ANGLE, - N_("Constrain angle"), {} }, - { "horiz", Command::HORIZONTAL, - N_("Constrain to be horizontal"), {} }, - { "vert", Command::VERTICAL, - N_("Constrain to be vertical"), {} }, - { "parallel", Command::PARALLEL, - N_("Constrain to be parallel or tangent"), {} }, - { "perpendicular", Command::PERPENDICULAR, - N_("Constrain to be perpendicular"), {} }, - { "pointonx", Command::ON_ENTITY, - N_("Constrain point on line / curve / plane / point"), {} }, - { "symmetric", Command::SYMMETRIC, - N_("Constrain symmetric"), {} }, - { "equal", Command::EQUAL, - N_("Constrain equal length / radius / angle"), {} }, - { "same-orientation",Command::ORIENTED_SAME, - N_("Constrain normals in same orientation"), {} }, - { "other-supp", Command::OTHER_ANGLE, - N_("Other supplementary angle"), {} }, - { "ref", Command::REFERENCE, - N_("Toggle reference dimension"), {} }, - { "", Command::NONE, "", {} }, - - { "extrude", Command::GROUP_EXTRUDE, - N_("New group extruding active sketch"), {} }, - { "lathe", Command::GROUP_LATHE, - N_("New group rotating active sketch"), {} }, - { "helix", Command::GROUP_HELIX, - N_("New group helix from active sketch"), {} }, - { "revolve", Command::GROUP_REVOLVE, - N_("New group revolve active sketch"), {} }, - { "step-rotate", Command::GROUP_ROT, - N_("New group step and repeat rotating"), {} }, - { "step-translate", Command::GROUP_TRANS, - N_("New group step and repeat translating"), {} }, - { "sketch-in-plane", Command::GROUP_WRKPL, - N_("New group in new workplane (thru given entities)"), {} }, - { "sketch-in-3d", Command::GROUP_3D, - N_("New group in 3d"), {} }, - { "assemble", Command::GROUP_LINK, - N_("New group linking / assembling file"), {} }, - { "", Command::NONE, "", {} }, - - { "in3d", Command::NEAREST_ISO, - N_("Nearest isometric view"), {} }, - { "ontoworkplane", Command::ONTO_WORKPLANE, - N_("Align view to active workplane"), {} }, + // name command keep_active tooltip pixmap + { "line", Command::LINE_SEGMENT, 1, N_("Sketch line segment"), {} }, + { "rectangle", Command::RECTANGLE, 1, N_("Sketch rectangle"), {} }, + { "circle", Command::CIRCLE, 1, N_("Sketch circle"), {} }, + { "arc", Command::ARC, 1, N_("Sketch arc of a circle"), {} }, + { "text", Command::TTF_TEXT, 1, N_("Sketch curves from text in a TrueType font"), {} }, + { "image", Command::IMAGE, 1, N_("Sketch image from a file"), {} }, + { "tangent-arc", Command::TANGENT_ARC, 1, N_("Create tangent arc at selected point"), {} }, + { "bezier", Command::CUBIC, 1, N_("Sketch cubic Bezier spline"), {} }, + { "point", Command::DATUM_POINT, 1, N_("Sketch datum point"), {} }, + { "construction", Command::CONSTRUCTION, 1, N_("Toggle construction"), {} }, + { "trim", Command::SPLIT_CURVES, 1, N_("Split lines / curves where they intersect"), {} }, + { "", Command::NONE, 0, "", {} }, + + { "length", Command::DISTANCE_DIA, 1, N_("Constrain distance / diameter / length"), {} }, + { "angle", Command::ANGLE, 1, N_("Constrain angle"), {} }, + { "horiz", Command::HORIZONTAL, 1, N_("Constrain to be horizontal"), {} }, + { "vert", Command::VERTICAL, 1, N_("Constrain to be vertical"), {} }, + { "parallel", Command::PARALLEL, 1, N_("Constrain to be parallel or tangent"), {} }, + { "perpendicular", Command::PERPENDICULAR, 1, N_("Constrain to be perpendicular"), {} }, + { "pointonx", Command::ON_ENTITY, 1, N_("Constrain point on line / curve / plane / point"), {} }, + { "symmetric", Command::SYMMETRIC, 1, N_("Constrain symmetric"), {} }, + { "equal", Command::EQUAL, 1, N_("Constrain equal length / radius / angle"), {} }, + { "same-orientation",Command::ORIENTED_SAME, 1, N_("Constrain normals in same orientation"), {} }, + { "other-supp", Command::OTHER_ANGLE, 1, N_("Other supplementary angle"), {} }, + { "ref", Command::REFERENCE, 1, N_("Toggle reference dimension"), {} }, + { "", Command::NONE, 0, "", {} }, + + { "extrude", Command::GROUP_EXTRUDE, 1, N_("New group extruding active sketch"), {} }, + { "lathe", Command::GROUP_LATHE, 1, N_("New group rotating active sketch"), {} }, + { "helix", Command::GROUP_HELIX, 1, N_("New group helix from active sketch"), {} }, + { "revolve", Command::GROUP_REVOLVE, 1, N_("New group revolve active sketch"), {} }, + { "step-rotate", Command::GROUP_ROT, 1, N_("New group step and repeat rotating"), {} }, + { "step-translate", Command::GROUP_TRANS, 1, N_("New group step and repeat translating"), {} }, + { "sketch-in-plane", Command::GROUP_WRKPL, 1, N_("New group in new workplane (thru given entities)"), {} }, + { "sketch-in-3d", Command::GROUP_3D, 1, N_("New group in 3d"), {} }, + { "assemble", Command::GROUP_LINK, 1, N_("New group linking / assembling file"), {} }, + { "", Command::NONE, "", 0, {} }, + + { "in3d", Command::NEAREST_ISO, 0, N_("Nearest isometric view"), {} }, + { "ontoworkplane", Command::ONTO_WORKPLANE, 0, N_("Align view to active workplane"), {} }, }; +bool GraphicsWindow::CheckIfKeepCommandActive(Command theCom) { + for(ToolIcon &icon : Toolbar) { + if(theCom == icon.command) { + if(icon.keep_active) + return true; + else + return false; + } + } + + return false; // no match found +} + + void GraphicsWindow::ToolbarDraw(UiCanvas *canvas) { ToolbarDrawOrHitTest(0, 0, canvas, NULL, NULL, NULL); } diff --git a/src/ui.h b/src/ui.h index c4ffff2ba..d2db7fad7 100644 --- a/src/ui.h +++ b/src/ui.h @@ -127,6 +127,7 @@ enum class Command : uint32_t { SPLIT_CURVES, TANGENT_ARC, CONSTRUCTION, + ALTERNATE_TOOL, // Group GROUP_3D, GROUP_WRKPL, @@ -660,7 +661,7 @@ class GraphicsWindow { struct { Pending operation; Command command; - + Command stored_command; hRequest request; hEntity point; List points; @@ -675,7 +676,10 @@ class GraphicsWindow { bool hasSuggestion; Constraint::Type suggestion; } pending; - void ClearPending(bool scheduleShowTW = true); + + Command activeTool; + void AlternateTool(); + void ClearPending(bool scheduleShowTW = true, bool allowCommandToContinue = true); bool IsFromPending(hRequest r); void AddToPending(hRequest r); void ReplacePending(hRequest before, hRequest after); @@ -798,6 +802,7 @@ class GraphicsWindow { void ToolbarDraw(UiCanvas *canvas); bool ToolbarMouseMoved(int x, int y); bool ToolbarMouseDown(int x, int y); + bool GraphicsWindow::CheckIfKeepCommandActive(Command theCom); Command toolbarHovered; // This sets what gets displayed. From f133324b0040041139e3ea487cb354e2e89dc772 Mon Sep 17 00:00:00 2001 From: Dustin Hartlyn Date: Sun, 6 Mar 2022 23:23:05 -0800 Subject: [PATCH 6/7] Escape, AlternateTool() & right-click will now remove any incomplete curve in the process of being placed. It will also reselect the latest tool, but unselect the tool if no cure is in the process of being drawn. Acomplished by using UndoUndo function which undoes the action registered after the operation is canceled, but does not add it to the redo stack so that Redo will not add the curve that was removed by the cancel operation. CancelPending is the main function added to facilitate any trigure that cancels the current action in process. UndoUndo was altered to not store the undone action if false is passed in as an aurgument. AlternateTool was also updated to work more efficently with CancelPending. Last a specific command was added to the MenuEdit function for the escape key. --- src/graphicswin.cpp | 5 +++++ src/mouse.cpp | 8 +++++--- src/undoredo.cpp | 3 ++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/graphicswin.cpp b/src/graphicswin.cpp index 7901c4cf1..2ac06778a 100644 --- a/src/graphicswin.cpp +++ b/src/graphicswin.cpp @@ -1095,11 +1095,16 @@ void GraphicsWindow::MenuEdit(Command id) { } } } + if(SS.GW.pending.operation != SS.GW.Pending::NONE) { + // Undo partially completed operation if there is one in process and dont remeber it. + SS.UndoUndo(); + } SS.GW.ClearSuper(); SS.TW.HideEditControl(); SS.nakedEdges.Clear(); SS.justExportedInfo.draw = false; SS.centerOfMass.draw = false; + //SS.GW.pending.operation; // This clears the marks drawn to indicate which points are // still free to drag. for(Param &p : SK.param) { diff --git a/src/mouse.cpp b/src/mouse.cpp index b5961687e..4769fe979 100644 --- a/src/mouse.cpp +++ b/src/mouse.cpp @@ -471,10 +471,11 @@ void GraphicsWindow::AlternateTool() { // Switches between most recent tool and the mouse selector if(SS.GW.activeTool != Command::NONE) { if(pending.command == Command::NONE) { - ClearPending(true, false); + SS.GW.MenuEdit(Command::UNSELECT_ALL); MenuRequest(SS.GW.activeTool); - // rechose tool through menu? - } else ClearPending(true, false); + } else { + ClearPending(true, false); + } SS.GW.Invalidate(); SS.ScheduleShowTW(); } @@ -487,6 +488,7 @@ void GraphicsWindow::ClearPending(bool scheduleShowTW, bool allowCommandToContin pending.points.Clear(); pending.requests.Clear(); + if(pending.command != Command::NONE && allowCommandToContinue) { if(CheckIfKeepCommandActive(pending.command)) { diff --git a/src/undoredo.cpp b/src/undoredo.cpp index 8ea8a0679..b875fbc7f 100644 --- a/src/undoredo.cpp +++ b/src/undoredo.cpp @@ -8,13 +8,14 @@ #include "solvespace.h" void SolveSpaceUI::UndoRemember() { - unsaved = true; + unsaved = true; // current interation of file is not saved PushFromCurrentOnto(&undo); UndoClearStack(&redo); UndoEnableMenus(); } void SolveSpaceUI::UndoUndo() { +// Will undo last operations without remebering it for redo if(undo.cnt <= 0) return; PushFromCurrentOnto(&redo); From f627ffb1825b5aa5334f255fedee2ba685675721 Mon Sep 17 00:00:00 2001 From: Dustin Hartlyn Date: Mon, 7 Mar 2022 19:13:26 -0800 Subject: [PATCH 7/7] Test fix in ui.h for working on mac/umbuntu --- src/graphicswin.cpp | 15 ++++++++++----- src/mouse.cpp | 29 +++++++++++++++++++---------- src/solvespace.h | 2 +- src/toolbar.cpp | 1 + src/ui.h | 4 +++- src/undoredo.cpp | 7 ++++--- 6 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/graphicswin.cpp b/src/graphicswin.cpp index 2ac06778a..4058ee930 100644 --- a/src/graphicswin.cpp +++ b/src/graphicswin.cpp @@ -74,7 +74,7 @@ const MenuEntry Menu[] = { { 1, NULL, Command::NONE, 0, KN, NULL }, { 1, N_("Select &Edge Chain"), Command::SELECT_CHAIN, C|'e', KN, mEdit }, { 1, N_("Select &All"), Command::SELECT_ALL, C|'a', KN, mEdit }, -{ 1, N_("&Unselect All"), Command::UNSELECT_ALL, '\x1b', KN, mEdit }, +{ 1, N_("&Unselect All"), Command::ESCAPE_KEY, '\x1b', KN, mEdit }, // x1b = escape key { 1, NULL, Command::NONE, 0, KN, NULL }, { 1, N_("&Line Styles..."), Command::EDIT_LINE_STYLES, 0, KN, mEdit }, { 1, N_("&View Projection..."), Command::VIEW_PROJECTION, 0, KN, mEdit }, @@ -245,7 +245,7 @@ bool GraphicsWindow::KeyboardEvent(Platform::KeyboardEvent event) { if(event.key == KeyboardEvent::Key::CHARACTER) { if(event.chr == '\b') { // Treat backspace identically to escape. - MenuEdit(Command::UNSELECT_ALL); + SS.GW.CancelPending(); return true; } else if(event.chr == '=') { // Treat = as +. This is specific to US (and US-compatible) keyboard layouts, @@ -1005,6 +1005,7 @@ void GraphicsWindow::EnsureValidActives() { void GraphicsWindow::SetWorkplaneFreeIn3d() { SK.GetGroup(activeGroup)->activeWorkplane = Entity::FREE_IN_3D; } + hEntity GraphicsWindow::ActiveWorkplane() { Group *g = SK.group.FindByIdNoOops(activeGroup); if(g) { @@ -1095,9 +1096,9 @@ void GraphicsWindow::MenuEdit(Command id) { } } } - if(SS.GW.pending.operation != SS.GW.Pending::NONE) { + if(SS.GW.pending.operation != Pending::COMMAND) { // Undo partially completed operation if there is one in process and dont remeber it. - SS.UndoUndo(); + SS.UndoUndo(false); } SS.GW.ClearSuper(); SS.TW.HideEditControl(); @@ -1121,7 +1122,11 @@ void GraphicsWindow::MenuEdit(Command id) { case Command::ALTERNATE_TOOL: SS.GW.AlternateTool(); break; - + + case Command::ESCAPE_KEY: + SS.GW.CancelPending(); + break; + case Command::SELECT_ALL: { for(Entity &e : SK.entity) { if(e.group != SS.GW.activeGroup) continue; diff --git a/src/mouse.cpp b/src/mouse.cpp index 4769fe979..1ceb38bf9 100644 --- a/src/mouse.cpp +++ b/src/mouse.cpp @@ -470,25 +470,37 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown, void GraphicsWindow::AlternateTool() { // Switches between most recent tool and the mouse selector if(SS.GW.activeTool != Command::NONE) { - if(pending.command == Command::NONE) { - SS.GW.MenuEdit(Command::UNSELECT_ALL); + // need to make sure there is actually a pending action or else it will undo a previous curve + if(pending.command == Command::NONE && pending.operation == Pending::NONE) { MenuRequest(SS.GW.activeTool); } else { - ClearPending(true, false); + SS.GW.CancelPending(); } SS.GW.Invalidate(); SS.ScheduleShowTW(); } } + +void GraphicsWindow::CancelPending() { + if(pending.operation != Pending::NONE && pending.operation != Pending::COMMAND) { + // undo any pending object and reselect the tool to be used again + SS.GW.MenuEdit(Command::UNSELECT_ALL); + ClearPending(true, false); + MenuRequest(SS.GW.activeTool); + } else + // If there is not an in process object to cancel, unselect the tool + ClearPending(true, false); + Invalidate(); + SS.ScheduleShowTW(); +} + void GraphicsWindow::ClearPending(bool scheduleShowTW, bool allowCommandToContinue) { // Clears selected tool or, steps of a tool's use (tow point rectangle). // Allows tool to be reactivated after use if specified in toolbar.cpp/Toolbar[] Command temp_store = Command::NONE; pending.points.Clear(); pending.requests.Clear(); - - if(pending.command != Command::NONE && allowCommandToContinue) { if(CheckIfKeepCommandActive(pending.command)) { @@ -567,11 +579,8 @@ void GraphicsWindow::MouseRightUp(double x, double y) { pending.operation == Pending::DRAGGING_NEW_POINT ) { - // Special case; use a right click to stop drawing lines, since - // a left click would draw another one. This is quicker and more - // intuitive than hitting escape. Likewise for other entities - // for consistency. - ClearPending(); + // Right click cancels pending operation. Same as escape/backspace. + CancelPending(); return; } diff --git a/src/solvespace.h b/src/solvespace.h index 1c22db629..971d83660 100644 --- a/src/solvespace.h +++ b/src/solvespace.h @@ -550,7 +550,7 @@ class SolveSpaceUI { void UndoEnableMenus(); void UndoRemember(); - void UndoUndo(); + void UndoUndo(bool save_undo = true); void UndoRedo(); void PushFromCurrentOnto(UndoStack *uk); void PopOntoCurrentFrom(UndoStack *uk); diff --git a/src/toolbar.cpp b/src/toolbar.cpp index 6bd4c38a3..9ff55ed90 100644 --- a/src/toolbar.cpp +++ b/src/toolbar.cpp @@ -58,6 +58,7 @@ static ToolIcon Toolbar[] = { { "ontoworkplane", Command::ONTO_WORKPLANE, 0, N_("Align view to active workplane"), {} }, }; + bool GraphicsWindow::CheckIfKeepCommandActive(Command theCom) { for(ToolIcon &icon : Toolbar) { if(theCom == icon.command) { diff --git a/src/ui.h b/src/ui.h index d2db7fad7..b1c527707 100644 --- a/src/ui.h +++ b/src/ui.h @@ -128,6 +128,7 @@ enum class Command : uint32_t { TANGENT_ARC, CONSTRUCTION, ALTERNATE_TOOL, + ESCAPE_KEY, // Group GROUP_3D, GROUP_WRKPL, @@ -679,6 +680,7 @@ class GraphicsWindow { Command activeTool; void AlternateTool(); + void CancelPending(); void ClearPending(bool scheduleShowTW = true, bool allowCommandToContinue = true); bool IsFromPending(hRequest r); void AddToPending(hRequest r); @@ -802,7 +804,7 @@ class GraphicsWindow { void ToolbarDraw(UiCanvas *canvas); bool ToolbarMouseMoved(int x, int y); bool ToolbarMouseDown(int x, int y); - bool GraphicsWindow::CheckIfKeepCommandActive(Command theCom); + bool CheckIfKeepCommandActive(Command theCom); Command toolbarHovered; // This sets what gets displayed. diff --git a/src/undoredo.cpp b/src/undoredo.cpp index b875fbc7f..9706ed63d 100644 --- a/src/undoredo.cpp +++ b/src/undoredo.cpp @@ -14,11 +14,12 @@ void SolveSpaceUI::UndoRemember() { UndoEnableMenus(); } -void SolveSpaceUI::UndoUndo() { -// Will undo last operations without remebering it for redo + +void SolveSpaceUI::UndoUndo(bool save_undo /*remeber undo for redo call, default is true*/) { + // Will undo last operations without remebering it for redo if(undo.cnt <= 0) return; - PushFromCurrentOnto(&redo); + if(save_undo) PushFromCurrentOnto(&redo); PopOntoCurrentFrom(&undo); UndoEnableMenus(); }