Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions gui-js/apps/minsky-electron/src/app/managers/ContextMenuManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,10 @@ export class ContextMenuManager {
label: 'Add item to a publication tab',
submenu: await ContextMenuManager.pubTabMenu(),
}),
new MenuItem({
label: 'Align',
submenu: Menu.buildFromTemplate(this.alignmentMenu()),
}),
new MenuItem({
label: `Delete ${itemInfo.classType}`,
click: () => CommandsManager.deleteCurrentItemHavingId(itemInfo.id)
Expand Down Expand Up @@ -1403,5 +1407,24 @@ export class ContextMenuManager {
]);
menu.popup();
}

static alignmentMenu() {
const labels: [string, string][] = [
['left', 'Left'],
['centre', 'Centre'],
['right', 'Right'],
['left_right', 'Left & Right'],
['top', 'Top'],
['middle', 'Middle'],
['bottom', 'Bottom'],
['top_bottom', 'Top & Bottom'],
];
return labels.map(([alignment, label]) =>
new MenuItem({
label,
click: async ()=>{await minsky.canvas.alignSelection(alignment);},
})
);
}
}

2 changes: 2 additions & 0 deletions gui-js/libs/shared/src/lib/backend/minsky.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,7 @@ export class Canvas extends RenderNativeWindow {
async addSheet(): Promise<void> {return this.$callMethod('addSheet');}
async addSwitch(): Promise<void> {return this.$callMethod('addSwitch');}
async addVariable(a1: string,a2: string): Promise<void> {return this.$callMethod('addVariable',a1,a2);}
async alignSelection(a1: string): Promise<void> {return this.$callMethod('alignSelection',a1);}
async applyDefaultPlotOptions(): Promise<void> {return this.$callMethod('applyDefaultPlotOptions');}
async clickType(...args: string[]): Promise<string> {return this.$callMethod('clickType',...args);}
async closestInPort(a1: number,a2: number): Promise<object> {return this.$callMethod('closestInPort',a1,a2);}
Expand Down Expand Up @@ -1941,6 +1942,7 @@ export class Selection extends CppClass {
async addWire(...args: any[]): Promise<object> {return this.$callMethod('addWire',...args);}
async adjustBookmark(): Promise<void> {return this.$callMethod('adjustBookmark');}
async adjustWiresGroup(a1: Wire): Promise<void> {return this.$callMethod('adjustWiresGroup',a1);}
async align(a1: Item,a2: string): Promise<void> {return this.$callMethod('align',a1,a2);}
async arguments(): Promise<string> {return this.$callMethod('arguments');}
async autoLayout(): Promise<void> {return this.$callMethod('autoLayout');}
async bookmark(...args: boolean[]): Promise<boolean> {return this.$callMethod('bookmark',...args);}
Expand Down
9 changes: 9 additions & 0 deletions model/canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,15 @@ namespace minsky
/// select all items in a given region
void select(const LassoBox&);

/// align items in selection using the current context item as the anchor.
/// No-op when there is no current item (for example, no right-clicked item);
/// callers should only expose/enable this action when an anchor item exists.
void alignSelection(Selection::Align align)
{
if (item)
selection.align(*item,align);
}

int ravelsSelected() const; ///< number of ravels in selection

/// sets itemFocus, and resets mouse offset for placement
Expand Down
40 changes: 39 additions & 1 deletion model/selection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,45 @@ namespace minsky
return true;
return false;
}


void Selection::align(const Item& ref, Align align)
{
auto apply=[&](const auto& i)
{
switch (align)
{
case left:
i->moveTo(i->x()+ref.left()-i->left(), i->y());
break;
case centre:
i->moveTo(ref.x(), i->y());
break;
case right:
i->moveTo(i->x()+ref.right()-i->right(), i->y());
break;
case left_right:
i->iWidth(ref.iWidth());
i->moveTo(ref.x(), i->y());
break;
case top:
i->moveTo(i->x(), i->y()+ref.top()-i->top());
break;
case middle:
i->moveTo(i->x(), ref.y());
break;
case bottom:
i->moveTo(i->x(), i->y()+ref.bottom()-i->bottom());
break;
case top_bottom:
i->iHeight(ref.iHeight());
i->moveTo(i->x(), ref.y());
break;
}
Comment thread
highperformancecoder marked this conversation as resolved.
};

for (auto& i: items) apply(i);
for (auto& g: groups) apply(g);
}
Comment thread
highperformancecoder marked this conversation as resolved.
}

CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(minsky::Selection);
4 changes: 4 additions & 0 deletions model/selection.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ namespace minsky
/// return if item is contained in selection
bool contains(const ItemPtr& item) const;
using Item::contains;

enum Align {left, centre, right, left_right, top, middle, bottom, top_bottom};
/// Align items in this selection with the reference item
void align(const Item&, Align);
};

}
Expand Down
Loading