Tweak drag and selection behavior: selection is kept after dragging
selected entities, but cleared after dragging an unselected entity. Marquee selection is select-only (not toggle), and "Select All" replaces "Invert Selection". Left-click on nothing will clear the selection. Also add context menu entries for cut, copy, and paste. [git-p4: depot-paths = "//depot/solvespace/": change = 2089]
This commit is contained in:
parent
c225087ab5
commit
ee052b556a
|
@ -139,10 +139,10 @@ void GraphicsWindow::PasteClipboard(Vector trans, double theta, double scale) {
|
|||
SS.GenerateAll(-1, -1);
|
||||
SS.MarkGroupDirty(r->group);
|
||||
bool hasDistance;
|
||||
int pts;
|
||||
int i, pts;
|
||||
EntReqTable::GetRequestInfo(r->type, r->extraPoints,
|
||||
NULL, &pts, NULL, &hasDistance);
|
||||
for(int i = 0; i < pts; i++) {
|
||||
for(i = 0; i < pts; i++) {
|
||||
Vector pt = cr->point[i];
|
||||
// We need the reflection to occur within the workplane; it may
|
||||
// otherwise correspond to just a rotation as projected.
|
||||
|
@ -165,6 +165,9 @@ void GraphicsWindow::PasteClipboard(Vector trans, double theta, double scale) {
|
|||
|
||||
cr->newReq = hr;
|
||||
ToggleSelectionStateOf(hr.entity(0));
|
||||
for(i = 0; i < pts; i++) {
|
||||
ToggleSelectionStateOf(hr.entity(i+1));
|
||||
}
|
||||
}
|
||||
|
||||
Constraint *c;
|
||||
|
|
20
draw.cpp
20
draw.cpp
|
@ -93,6 +93,19 @@ void GraphicsWindow::ClearNonexistentSelectionItems(void) {
|
|||
if(change) InvalidateGraphics();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Is this entity selected?
|
||||
//-----------------------------------------------------------------------------
|
||||
bool GraphicsWindow::EntityIsSelected(hEntity he) {
|
||||
Selection *s;
|
||||
for(s = selection.First(); s; s = selection.NextAfter(s)) {
|
||||
if(s->entity.v == he.v) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Toggle the selection state of the indicated item: if it was selected then
|
||||
// un-select it, and if it wasn't then select it.
|
||||
|
@ -136,7 +149,12 @@ void GraphicsWindow::ToggleSelectionStateOf(Selection *stog, bool batch) {
|
|||
}
|
||||
}
|
||||
}
|
||||
selection.RemoveTagged();
|
||||
|
||||
// It's too confusing to make operations that select multiple entities
|
||||
// (like marquee selection) toggle. So make those select-only.
|
||||
if(!batch) {
|
||||
selection.RemoveTagged();
|
||||
}
|
||||
if(wasSelected) return;
|
||||
|
||||
// So it's not selected, so we should select it.
|
||||
|
|
|
@ -44,7 +44,7 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
|||
{ 1, "&Delete\tDel", MNU_DELETE, 127, mClip },
|
||||
{ 1, NULL, 0, NULL },
|
||||
{ 1, "Select &Edge Chain\tCtrl+E", MNU_SELECT_CHAIN, 'E'|C, mEdit },
|
||||
{ 1, "Invert &Selection\tCtrl+A", MNU_INVERT_SEL, 'A'|C, mEdit },
|
||||
{ 1, "Select &All\tCtrl+A", MNU_SELECT_ALL, 'A'|C, mEdit },
|
||||
{ 1, "&Unselect All\tEsc", MNU_UNSELECT_ALL, 27, mEdit },
|
||||
|
||||
{ 0, "&View", 0, NULL },
|
||||
|
@ -626,7 +626,7 @@ void GraphicsWindow::MenuEdit(int id) {
|
|||
SS.nakedEdges.Clear();
|
||||
break;
|
||||
|
||||
case MNU_INVERT_SEL: {
|
||||
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;
|
||||
|
|
66
mouse.cpp
66
mouse.cpp
|
@ -177,8 +177,21 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
|||
pending.normal = hover.entity;
|
||||
pending.operation = DRAGGING_NORMAL;
|
||||
} else {
|
||||
if(EntityIsSelected(e->h)) {
|
||||
// The entity is selected, which means that it wasn't
|
||||
// before the user clicked to start dragging, which
|
||||
// means they're dragging just the hovered thing,
|
||||
// not the full selection. So clear all the selection
|
||||
// except that entity.
|
||||
ClearSelection();
|
||||
ToggleSelectionStateOf(e->h);
|
||||
}
|
||||
StartDraggingBySelection();
|
||||
ClearSelection();
|
||||
// If something's hovered, then the user selected it when
|
||||
// they clicked to start dragging, but they probably
|
||||
// didn't mean to select it. Or if it was selected, then
|
||||
// they didn't mean to deselect it. So fix that.
|
||||
ToggleSelectionStateOf(e->h);
|
||||
hover.Clear();
|
||||
pending.operation = DRAGGING_POINTS;
|
||||
}
|
||||
|
@ -488,7 +501,11 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
|
|||
context.active = true;
|
||||
|
||||
GroupSelection();
|
||||
if(hover.IsEmpty() && gs.n == 0 && gs.constraints == 0) {
|
||||
if(hover.IsEmpty() &&
|
||||
gs.n == 0 &&
|
||||
gs.constraints == 0 &&
|
||||
(SS.clipboard.r.n == 0 || !LockedInWorkplane()))
|
||||
{
|
||||
// No reason to display a context menu.
|
||||
goto done;
|
||||
}
|
||||
|
@ -574,6 +591,17 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
|
|||
CMNU_SELECT_CHAIN);
|
||||
}
|
||||
AddContextMenuItem(NULL, CONTEXT_SEPARATOR);
|
||||
if(LockedInWorkplane()) {
|
||||
AddContextMenuItem("Cut Selection", CMNU_CUT_SEL);
|
||||
AddContextMenuItem("Copy Selection", CMNU_COPY_SEL);
|
||||
}
|
||||
}
|
||||
|
||||
if(SS.clipboard.r.n > 0 && LockedInWorkplane()) {
|
||||
AddContextMenuItem("Paste Selection", CMNU_PASTE_SEL);
|
||||
}
|
||||
|
||||
if(!selEmpty) {
|
||||
AddContextMenuItem("Delete Selection", CMNU_DELETE_SEL);
|
||||
AddContextMenuItem("Unselect All", CMNU_UNSELECT_ALL);
|
||||
}
|
||||
|
@ -591,6 +619,18 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
|
|||
MenuEdit(MNU_SELECT_CHAIN);
|
||||
break;
|
||||
|
||||
case CMNU_CUT_SEL:
|
||||
MenuClipboard(MNU_CUT);
|
||||
break;
|
||||
|
||||
case CMNU_COPY_SEL:
|
||||
MenuClipboard(MNU_COPY);
|
||||
break;
|
||||
|
||||
case CMNU_PASTE_SEL:
|
||||
MenuClipboard(MNU_PASTE);
|
||||
break;
|
||||
|
||||
case CMNU_DELETE_SEL:
|
||||
MenuClipboard(MNU_DELETE);
|
||||
break;
|
||||
|
@ -679,8 +719,10 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
|
|||
default:
|
||||
if(ret >= CMNU_FIRST_STYLE) {
|
||||
Style::AssignSelectionToStyle(ret - CMNU_FIRST_STYLE);
|
||||
} else {
|
||||
// otherwise it was cancelled, so do nothing
|
||||
contextMenuCancelTime = GetMilliseconds();
|
||||
}
|
||||
// otherwise it was cancelled, so do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1024,7 +1066,9 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
|||
case 0:
|
||||
default:
|
||||
ClearPending();
|
||||
ToggleSelectionStateOf(&hover);
|
||||
if(hover.entity.v || hover.constraint.v) {
|
||||
ToggleSelectionStateOf(&hover);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1050,6 +1094,20 @@ void GraphicsWindow::MouseLeftUp(double mx, double my) {
|
|||
InvalidateGraphics();
|
||||
break;
|
||||
|
||||
case 0:
|
||||
// We need to clear the selection here, and not in the mouse down
|
||||
// event, since a mouse down without anything hovered could also
|
||||
// be the start of marquee selection. But don't do that on the
|
||||
// left click to cancel a context menu. The time delay is an ugly
|
||||
// hack.
|
||||
if(hover.IsEmpty() &&
|
||||
(contextMenuCancelTime == 0 ||
|
||||
(GetMilliseconds() - contextMenuCancelTime) > 200))
|
||||
{
|
||||
ClearSelection();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break; // do nothing
|
||||
}
|
||||
|
|
27
ui.h
27
ui.h
|
@ -265,7 +265,7 @@ public:
|
|||
MNU_PASTE_TRANSFORM,
|
||||
MNU_DELETE,
|
||||
MNU_SELECT_CHAIN,
|
||||
MNU_INVERT_SEL,
|
||||
MNU_SELECT_ALL,
|
||||
MNU_SNAP_TO_GRID,
|
||||
MNU_ROTATE_90,
|
||||
MNU_UNSELECT_ALL,
|
||||
|
@ -486,24 +486,29 @@ public:
|
|||
int n;
|
||||
} gs;
|
||||
void GroupSelection(void);
|
||||
bool EntityIsSelected(hEntity he);
|
||||
void ToggleSelectionStateOf(hEntity he, bool batch=false);
|
||||
void ToggleSelectionStateOf(Selection *s, bool batch=false);
|
||||
void SelectByMarquee(void);
|
||||
void ClearSuper(void);
|
||||
|
||||
static const int CMNU_UNSELECT_ALL = 0x100;
|
||||
static const int CMNU_DELETE_SEL = 0x101;
|
||||
static const int CMNU_NEW_CUSTOM_STYLE = 0x102;
|
||||
static const int CMNU_NO_STYLE = 0x103;
|
||||
static const int CMNU_GROUP_INFO = 0x104;
|
||||
static const int CMNU_REFERENCE_DIM = 0x105;
|
||||
static const int CMNU_OTHER_ANGLE = 0x106;
|
||||
static const int CMNU_DEL_COINCIDENT = 0x107;
|
||||
static const int CMNU_STYLE_INFO = 0x108;
|
||||
static const int CMNU_SNAP_TO_GRID = 0x109;
|
||||
static const int CMNU_SELECT_CHAIN = 0x10a;
|
||||
static const int CMNU_CUT_SEL = 0x101;
|
||||
static const int CMNU_COPY_SEL = 0x102;
|
||||
static const int CMNU_PASTE_SEL = 0x103;
|
||||
static const int CMNU_DELETE_SEL = 0x104;
|
||||
static const int CMNU_SELECT_CHAIN = 0x105;
|
||||
static const int CMNU_NEW_CUSTOM_STYLE = 0x110;
|
||||
static const int CMNU_NO_STYLE = 0x111;
|
||||
static const int CMNU_GROUP_INFO = 0x120;
|
||||
static const int CMNU_STYLE_INFO = 0x121;
|
||||
static const int CMNU_REFERENCE_DIM = 0x130;
|
||||
static const int CMNU_OTHER_ANGLE = 0x131;
|
||||
static const int CMNU_DEL_COINCIDENT = 0x132;
|
||||
static const int CMNU_SNAP_TO_GRID = 0x140;
|
||||
static const int CMNU_FIRST_STYLE = 0x40000000;
|
||||
void ContextMenuListStyles(void);
|
||||
SDWORD contextMenuCancelTime;
|
||||
|
||||
// The toolbar, in toolbar.cpp
|
||||
bool ToolbarDrawOrHitTest(int x, int y, bool paint, int *menu);
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
|
||||
de-select after left-clicking nothing, keep sel on drag?
|
||||
bbox selection is select-only, not toggle?
|
||||
show and modify view parameters (translate, rotate, scale)
|
||||
context menu to hide / suppress groups by entity?
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user