static bool ProcessKeyDown(WPARAM wParam) { if(GraphicsEditControlIsVisible() && wParam != VK_ESCAPE) { if(wParam == VK_RETURN) { char s[1024]; memset(s, 0, sizeof(s)); SendMessage(GraphicsEditControl, WM_GETTEXT, 900, (LPARAM)s); SS.GW.EditControlDone(s); return true; } else { return false; } } if(TextEditControlIsVisible() && wParam != VK_ESCAPE) { if(wParam == VK_RETURN) { char s[1024]; memset(s, 0, sizeof(s)); SendMessage(TextEditControl, WM_GETTEXT, 900, (LPARAM)s); SS.TW.EditControlDone(s); } else { return false; } } int c; switch(wParam) { case VK_OEM_PLUS: c = '+'; break; case VK_OEM_MINUS: c = '-'; break; case VK_ESCAPE: c = 27; break; case VK_OEM_1: c = ';'; break; case VK_OEM_3: c = '`'; break; case VK_OEM_4: c = '['; break; case VK_OEM_6: c = ']'; break; case VK_OEM_5: c = '\\'; break; case VK_OEM_PERIOD: c = '.'; break; case VK_SPACE: c = ' '; break; case VK_DELETE: c = 127; break; case VK_TAB: c = '\t'; break; case VK_BROWSER_BACK: case VK_BACK: c = '\b'; break; case VK_F1: case VK_F2: case VK_F3: case VK_F4: case VK_F5: case VK_F6: case VK_F7: case VK_F8: case VK_F9: case VK_F10: case VK_F11: case VK_F12: c = ((int)wParam - VK_F1) + 0xf1; break; // These overlap with some character codes that I'm using, so // don't let them trigger by accident. case VK_F16: case VK_INSERT: case VK_EXECUTE: case VK_APPS: case VK_LWIN: case VK_RWIN: return false; default: c = (int)wParam; break; } if(GetAsyncKeyState(VK_SHIFT) & 0x8000) c |= GraphicsWindow::SHIFT_MASK; if(GetAsyncKeyState(VK_CONTROL) & 0x8000) c |= GraphicsWindow::CTRL_MASK; switch(c) { case GraphicsWindow::SHIFT_MASK | '.': c = '>'; break; } for(int i = 0; SS.GW.menu[i].level >= 0; i++) { if(c == SS.GW.menu[i].accel) { (SS.GW.menu[i].fn)((GraphicsWindow::MenuId)SS.GW.menu[i].id); break; } } if(SS.GW.KeyDown(c)) return true; // No accelerator; process the key as normal. return false; }
void GraphicsWindow::MenuEdit(int id) { switch(id) { case MNU_UNSELECT_ALL: SS.GW.GroupSelection(); // If there's nothing selected to de-select, and no operation // to cancel, then perhaps they want to return to the home // screen in the text window. if(SS.GW.gs.n == 0 && SS.GW.gs.constraints == 0 && SS.GW.pending.operation == 0) { if(!(TextEditControlIsVisible() || GraphicsEditControlIsVisible())) { if(SS.TW.shown.screen == TextWindow::SCREEN_STYLE_INFO) { SS.TW.GoToScreen(TextWindow::SCREEN_LIST_OF_STYLES); } else { SS.TW.ClearSuper(); } } } SS.GW.ClearSuper(); SS.TW.HideEditControl(); SS.nakedEdges.Clear(); SS.justExportedInfo.draw = false; // This clears the marks drawn to indicate which points are // still free to drag. Param *p; for(p = SK.param.First(); p; p = SK.param.NextAfter(p)) { p->free = false; } if(SS.exportMode) { SS.exportMode = false; SS.GenerateAll(SolveSpaceUI::GENERATE_ALL); } break; case MNU_SELECT_ALL: { Entity *e; for(e = SK.entity.First(); e; e = SK.entity.NextAfter(e)) { if(e->group.v != SS.GW.activeGroup.v) continue; if(e->IsFace() || e->IsDistance()) continue; if(!e->IsVisible()) continue; SS.GW.MakeSelected(e->h); } InvalidateGraphics(); SS.ScheduleShowTW(); break; } case MNU_SELECT_CHAIN: { Entity *e; int newlySelected = 0; bool didSomething; do { didSomething = false; for(e = SK.entity.First(); e; e = SK.entity.NextAfter(e)) { if(e->group.v != SS.GW.activeGroup.v) continue; if(!e->HasEndpoints()) continue; if(!e->IsVisible()) continue; Vector st = e->EndpointStart(), fi = e->EndpointFinish(); bool onChain = false, alreadySelected = false; List<Selection> *ls = &(SS.GW.selection); for(Selection *s = ls->First(); s; s = ls->NextAfter(s)) { if(!s->entity.v) continue; if(s->entity.v == e->h.v) { alreadySelected = true; continue; } Entity *se = SK.GetEntity(s->entity); if(!se->HasEndpoints()) continue; Vector sst = se->EndpointStart(), sfi = se->EndpointFinish(); if(sst.Equals(st) || sst.Equals(fi) || sfi.Equals(st) || sfi.Equals(fi)) { onChain = true; } } if(onChain && !alreadySelected) { SS.GW.MakeSelected(e->h); newlySelected++; didSomething = true; } } } while(didSomething); if(newlySelected == 0) { Error("No additional entities share endpoints with the " "selected entities."); } InvalidateGraphics(); SS.ScheduleShowTW(); break; } case MNU_ROTATE_90: { SS.GW.GroupSelection(); Entity *e = NULL; if(SS.GW.gs.n == 1 && SS.GW.gs.points == 1) { e = SK.GetEntity(SS.GW.gs.point[0]); } else if(SS.GW.gs.n == 1 && SS.GW.gs.entities == 1) { e = SK.GetEntity(SS.GW.gs.entity[0]); } SS.GW.ClearSelection(); hGroup hg = e ? e->group : SS.GW.activeGroup; Group *g = SK.GetGroup(hg); if(g->type != Group::IMPORTED) { Error("To use this command, select a point or other " "entity from an imported part, or make an import " "group the active group."); break; } SS.UndoRemember(); // Rotate by ninety degrees about the coordinate axis closest // to the screen normal. Vector norm = SS.GW.projRight.Cross(SS.GW.projUp); norm = norm.ClosestOrtho(); norm = norm.WithMagnitude(1); Quaternion qaa = Quaternion::From(norm, PI/2); g->TransformImportedBy(Vector::From(0, 0, 0), qaa); // and regenerate as necessary. SS.MarkGroupDirty(hg); SS.GenerateAll(); break; } case MNU_SNAP_TO_GRID: { if(!SS.GW.LockedInWorkplane()) { Error("No workplane is active. Select a workplane to define " "the plane for the snap grid."); break; } SS.GW.GroupSelection(); if(SS.GW.gs.points == 0 && SS.GW.gs.constraintLabels == 0) { Error("Can't snap these items to grid; select points, " "text comments, or constraints with a label. " "To snap a line, select its endpoints."); break; } SS.UndoRemember(); List<Selection> *ls = &(SS.GW.selection); for(Selection *s = ls->First(); s; s = ls->NextAfter(s)) { if(s->entity.v) { hEntity hp = s->entity; Entity *ep = SK.GetEntity(hp); if(!ep->IsPoint()) continue; Vector p = ep->PointGetNum(); ep->PointForceTo(SS.GW.SnapToGrid(p)); SS.GW.pending.points.Add(&hp); SS.MarkGroupDirty(ep->group); } else if(s->constraint.v) { Constraint *c = SK.GetConstraint(s->constraint); c->disp.offset = SS.GW.SnapToGrid(c->disp.offset); } } // Regenerate, with these points marked as dragged so that they // get placed as close as possible to our snap grid. SS.GenerateAll(); SS.GW.ClearPending(); SS.GW.ClearSelection(); InvalidateGraphics(); break; } case MNU_UNDO: SS.UndoUndo(); break; case MNU_REDO: SS.UndoRedo(); break; case MNU_REGEN_ALL: SS.ReloadAllImported(); SS.GenerateAll(SolveSpaceUI::GENERATE_UNTIL_ACTIVE); SS.ScheduleShowTW(); break; default: oops(); } }