diff --git a/com.archimatetool.canvas/src/com/archimatetool/canvas/factory/CanvasStickyUIProvider.java b/com.archimatetool.canvas/src/com/archimatetool/canvas/factory/CanvasStickyUIProvider.java index 576c56627..449117a3b 100644 --- a/com.archimatetool.canvas/src/com/archimatetool/canvas/factory/CanvasStickyUIProvider.java +++ b/com.archimatetool.canvas/src/com/archimatetool/canvas/factory/CanvasStickyUIProvider.java @@ -62,6 +62,7 @@ public ImageDescriptor getImageDescriptor() { public boolean shouldExposeFeature(String featureName) { if(featureName == IArchimatePackage.Literals.LINE_OBJECT__LINE_COLOR.getName() || featureName == IArchimatePackage.Literals.LINE_OBJECT__LINE_WIDTH.getName() || + featureName == IDiagramModelObject.FEATURE_LINE_STYLE || featureName == IDiagramModelObject.FEATURE_DERIVE_ELEMENT_LINE_COLOR || featureName == IDiagramModelObject.FEATURE_GRADIENT) { return false; diff --git a/com.archimatetool.editor/plugin.xml b/com.archimatetool.editor/plugin.xml index cbfd28d39..e12938c0c 100644 --- a/com.archimatetool.editor/plugin.xml +++ b/com.archimatetool.editor/plugin.xml @@ -431,13 +431,13 @@ getAdaptableType() { - return IDiagramModelObject.class; - } - } - - private OpacityComposite fOpacityComposite; - - @Override - protected void createControls(Composite parent) { - fOpacityComposite = new OpacityComposite(this, parent, Messages.LineOpacitySection_0) { - @Override - Command getCommand(IDiagramModelObject dmo, int newValue) { - return new DiagramModelObjectOutlineAlphaCommand(dmo, newValue); - } - - @Override - int getValue() { - IDiagramModelObject lastSelected = (IDiagramModelObject)getFirstSelectedObject(); - return lastSelected.getLineAlpha(); - } - - @Override - boolean isValidObject(EObject eObject) { - return getFilter().isRequiredType(eObject); - } - }; - - // Help ID - PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, HELP_ID); - } - - @Override - protected void notifyChanged(Notification msg) { - Object feature = msg.getFeature(); - - if(isFeatureNotification(msg, IDiagramModelObject.FEATURE_LINE_ALPHA)) { - if(!fIsExecutingCommand) { - update(); - } - } - else if(feature == IArchimatePackage.Literals.LOCKABLE__LOCKED) { - update(); - } - } - - @Override - protected void update() { - fOpacityComposite.updateControl(); - } - - @Override - protected IObjectFilter getFilter() { - return new Filter(); - } - - @Override - public void dispose() { - super.dispose(); - - if(fOpacityComposite != null) { - fOpacityComposite.dispose(); - fOpacityComposite = null; - } - } -} diff --git a/com.archimatetool.editor/src/com/archimatetool/editor/propertysections/LineSection2.java b/com.archimatetool.editor/src/com/archimatetool/editor/propertysections/LineSection2.java new file mode 100644 index 000000000..72c801bb0 --- /dev/null +++ b/com.archimatetool.editor/src/com/archimatetool/editor/propertysections/LineSection2.java @@ -0,0 +1,155 @@ +/** + * This program and the accompanying materials + * are made available under the terms of the License + * which accompanies this distribution in the file LICENSE.txt + */ +package com.archimatetool.editor.propertysections; + +import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.gef.commands.Command; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.PlatformUI; + +import com.archimatetool.editor.diagram.commands.DiagramModelObjectOutlineAlphaCommand; +import com.archimatetool.model.IArchimatePackage; +import com.archimatetool.model.IDiagramModelObject; + + + +/** + * Property Section for Line Opacity and Line Style + * + * @author Phillip Beauvoir + */ +public class LineSection2 extends AbstractMultiControlSection { + + private static final String HELP_ID = "com.archimatetool.help.elementPropertySection"; //$NON-NLS-1$ + + /** + * Filter to show or reject this section depending on input value + */ + public static class Filter extends ObjectFilter { + @Override + public boolean isRequiredType(Object object) { + return object instanceof IDiagramModelObject dmo && + (shouldExposeFeature(dmo, IDiagramModelObject.FEATURE_LINE_ALPHA) || + shouldExposeFeature(dmo, IDiagramModelObject.FEATURE_LINE_STYLE)); + } + + @Override + public Class getAdaptableType() { + return IDiagramModelObject.class; + } + } + + private OpacityComposite opacityComposite; + private LineStyleComposite linestyleComposite; + + @Override + protected void createControls(Composite parent) { + init(parent, 2); + + // Help ID + PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, HELP_ID); + } + + @Override + protected void notifyChanged(Notification msg) { + Object feature = msg.getFeature(); + + if(isFeatureNotification(msg, IDiagramModelObject.FEATURE_LINE_ALPHA)) { + if(!fIsExecutingCommand) { + updateOpacityControl(); + } + } + else if(isFeatureNotification(msg, IDiagramModelObject.FEATURE_LINE_STYLE)) { + updateLineStyleControl(); + } + else if(feature == IArchimatePackage.Literals.LOCKABLE__LOCKED) { + update(); + } + } + + @Override + protected void update() { + updateOpacityControl(); + updateLineStyleControl(); + } + + private void updateOpacityControl() { + boolean show = shouldShowControl(IDiagramModelObject.FEATURE_LINE_ALPHA); + + if(show) { + if(opacityComposite == null) { + opacityComposite = new OpacityComposite(this, parentComposite, Messages.LineOpacitySection_0) { + @Override + Command getCommand(IDiagramModelObject dmo, int newValue) { + return new DiagramModelObjectOutlineAlphaCommand(dmo, newValue); + } + + @Override + int getValue() { + IDiagramModelObject lastSelected = (IDiagramModelObject)getFirstSelectedObject(); + return lastSelected.getLineAlpha(); + } + + @Override + boolean isValidObject(EObject eObject) { + return getFilter().shouldExposeFeature(eObject, IDiagramModelObject.FEATURE_LINE_ALPHA); + } + }; + + // If we're showing the LineStyleComposite move the OpacityComposite above/before it + if(linestyleComposite != null) { + opacityComposite.getComposite().moveAbove(linestyleComposite.getComposite()); + layout(); + } + } + + opacityComposite.updateControl(); + } + else if(opacityComposite != null) { + opacityComposite.dispose(); + opacityComposite = null; + layout(); + } + } + + private void updateLineStyleControl() { + boolean show = shouldShowControl(IDiagramModelObject.FEATURE_LINE_STYLE); + + if(show) { + if(linestyleComposite == null) { + linestyleComposite = new LineStyleComposite(this, parentComposite); + layout(); + } + linestyleComposite.updateControl(); + } + else if(linestyleComposite != null) { + linestyleComposite.dispose(); + linestyleComposite = null; + layout(); + } + } + + @Override + protected IObjectFilter getFilter() { + return new Filter(); + } + + @Override + public void dispose() { + super.dispose(); + + if(opacityComposite != null) { + opacityComposite.dispose(); + opacityComposite = null; + } + + if(linestyleComposite != null) { + linestyleComposite.dispose(); + linestyleComposite = null; + } + } +} diff --git a/com.archimatetool.editor/src/com/archimatetool/editor/propertysections/LineStyleComposite.java b/com.archimatetool.editor/src/com/archimatetool/editor/propertysections/LineStyleComposite.java new file mode 100644 index 000000000..a9c14d1dd --- /dev/null +++ b/com.archimatetool.editor/src/com/archimatetool/editor/propertysections/LineStyleComposite.java @@ -0,0 +1,136 @@ +/** + * This program and the accompanying materials + * are made available under the terms of the License + * which accompanies this distribution in the file LICENSE.txt + */ +package com.archimatetool.editor.propertysections; + +import static org.eclipse.swt.events.SelectionListener.widgetSelectedAdapter; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.gef.commands.Command; +import org.eclipse.gef.commands.CompoundCommand; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Menu; + +import com.archimatetool.editor.diagram.commands.DiagramModelObjectLineStyleCommand; +import com.archimatetool.editor.ui.IArchiImages; +import com.archimatetool.model.IDiagramModelObject; + + + +/** + * Diagram Object Line Style Composite + * + * @author Phillip Beauvoir + */ +class LineStyleComposite { + + private Button button; + private AbstractECorePropertySection section; + private Composite composite; + + LineStyleComposite(AbstractECorePropertySection section, Composite parent) { + this.section = section; + composite = section.createComposite(parent, 2, false); + createControls(composite); + } + + Composite getComposite() { + return composite; + } + + private void createControls(Composite parent) { + section.createLabel(parent, "Line Style:", ITabbedLayoutConstants.STANDARD_LABEL_WIDTH, SWT.CENTER); + + button = section.getWidgetFactory().createButton(parent, null, SWT.PUSH); + button.setLayoutData(GridDataFactory.swtDefaults().hint(50, SWT.DEFAULT).create()); // a bit more width + + button.addSelectionListener(widgetSelectedAdapter(event -> { + MenuManager menuManager = new MenuManager(); + + menuManager.add(createAction("Solid", 0, IArchiImages.ImageFactory.getImageDescriptor(IArchiImages.LINE_SOLID))); + menuManager.add(createAction("Dashed", 1, IArchiImages.ImageFactory.getImageDescriptor(IArchiImages.LINE_DASHED))); + menuManager.add(createAction("Dotted", 2, IArchiImages.ImageFactory.getImageDescriptor(IArchiImages.LINE_DOTTED))); + + Menu menu = menuManager.createContextMenu(button.getShell()); + Rectangle buttonBounds = button.getBounds(); + Point p = button.getParent().toDisplay(buttonBounds.x, buttonBounds.y + buttonBounds.height); + menu.setLocation(p); + menu.setVisible(true); + })); + } + + private IAction createAction(String text, final int value, final ImageDescriptor imageDesc) { + IAction action = new Action(text, IAction.AS_RADIO_BUTTON) { + @Override + public void run() { + CompoundCommand result = new CompoundCommand(); + + for(EObject object : section.getEObjects()) { + if(isValidObject(object)) { + Command cmd = new DiagramModelObjectLineStyleCommand((IDiagramModelObject)object, value); + if(cmd.canExecute()) { + result.add(cmd); + } + } + } + + section.executeCommand(result.unwrap()); + } + + @Override + public ImageDescriptor getImageDescriptor() { + return imageDesc; + } + }; + + action.setChecked(((IDiagramModelObject)section.getFirstSelectedObject()).getLineStyle() == value); + + return action; + } + + /** + * In case of multi-selection we should check this + */ + private boolean isValidObject(EObject eObject) { + return section.isAlive(eObject) && + section.getFilter().shouldExposeFeature(eObject, IDiagramModelObject.FEATURE_LINE_STYLE); + } + + void updateControl() { + IDiagramModelObject dmo = (IDiagramModelObject)section.getFirstSelectedObject(); + int lineStyle = dmo.getLineStyle(); + + switch(lineStyle) { + case 0: + default: + button.setImage(IArchiImages.ImageFactory.getImage(IArchiImages.LINE_SOLID)); + break; + case 1: + button.setImage(IArchiImages.ImageFactory.getImage(IArchiImages.LINE_DASHED)); + break; + case 2: + button.setImage(IArchiImages.ImageFactory.getImage(IArchiImages.LINE_DOTTED)); + break; + } + + button.setEnabled(!section.isLocked(dmo)); + } + + void dispose() { + composite.dispose(); + composite = null; + section = null; + button = null; + } +} diff --git a/com.archimatetool.editor/src/com/archimatetool/editor/ui/factory/sketch/SketchActorUIProvider.java b/com.archimatetool.editor/src/com/archimatetool/editor/ui/factory/sketch/SketchActorUIProvider.java index 0ad30e4d5..b7bbe6cfa 100644 --- a/com.archimatetool.editor/src/com/archimatetool/editor/ui/factory/sketch/SketchActorUIProvider.java +++ b/com.archimatetool.editor/src/com/archimatetool/editor/ui/factory/sketch/SketchActorUIProvider.java @@ -70,7 +70,8 @@ public boolean shouldExposeFeature(String featureName) { featureName == IDiagramModelObject.FEATURE_DERIVE_ELEMENT_LINE_COLOR || featureName == IDiagramModelObject.FEATURE_LINE_ALPHA || featureName == IArchimatePackage.Literals.DIAGRAM_MODEL_OBJECT__ALPHA.getName() || - featureName == IDiagramModelObject.FEATURE_GRADIENT) { + featureName == IDiagramModelObject.FEATURE_GRADIENT || + featureName == IDiagramModelObject.FEATURE_LINE_STYLE) { return false; } diff --git a/com.archimatetool.model/src/com/archimatetool/model/IDiagramModelObject.java b/com.archimatetool.model/src/com/archimatetool/model/IDiagramModelObject.java index f421d000e..439920d7f 100644 --- a/com.archimatetool.model/src/com/archimatetool/model/IDiagramModelObject.java +++ b/com.archimatetool.model/src/com/archimatetool/model/IDiagramModelObject.java @@ -45,6 +45,9 @@ public interface IDiagramModelObject extends IConnectable, IFontAttribute, ILine String FEATURE_DERIVE_ELEMENT_LINE_COLOR = "deriveElementLineColor"; boolean FEATURE_DERIVE_ELEMENT_LINE_COLOR_DEFAULT = true; + String FEATURE_LINE_STYLE = "lineStyle"; + int FEATURE_LINE_STYLE_DEFAULT = 0; + /** * @return the value of FEATURE_LINE_ALPHA */ @@ -100,6 +103,17 @@ public interface IDiagramModelObject extends IConnectable, IFontAttribute, ILine */ void setDeriveElementLineColor(boolean value); + /** + * @return the value of feature FEATURE_LINE_STYLE + */ + int getLineStyle(); + + /** + * Set the value of feature FEATURE_LINE_STYLE + * @param lineStyle + */ + void setLineStyle(int lineStyle); + /** * Returns the value of the 'Bounds' containment reference. * diff --git a/com.archimatetool.model/src/com/archimatetool/model/impl/DiagramModelObject.java b/com.archimatetool.model/src/com/archimatetool/model/impl/DiagramModelObject.java index cbf6d6183..c317a0d84 100644 --- a/com.archimatetool.model/src/com/archimatetool/model/impl/DiagramModelObject.java +++ b/com.archimatetool.model/src/com/archimatetool/model/impl/DiagramModelObject.java @@ -261,6 +261,16 @@ public void setDeriveElementLineColor(boolean value) { getFeatures().putBoolean(FEATURE_DERIVE_ELEMENT_LINE_COLOR, value, FEATURE_DERIVE_ELEMENT_LINE_COLOR_DEFAULT); } + @Override + public int getLineStyle() { + return getFeatures().getInt(FEATURE_LINE_STYLE, FEATURE_LINE_STYLE_DEFAULT); + } + + @Override + public void setLineStyle(int lineStyle) { + getFeatures().putInt(FEATURE_LINE_STYLE, lineStyle, FEATURE_LINE_STYLE_DEFAULT); + } + /** * * diff --git a/tests/com.archimatetool.model.tests/src/com/archimatetool/model/impl/DiagramModelObjectTests.java b/tests/com.archimatetool.model.tests/src/com/archimatetool/model/impl/DiagramModelObjectTests.java index 08867a184..3aed579c7 100644 --- a/tests/com.archimatetool.model.tests/src/com/archimatetool/model/impl/DiagramModelObjectTests.java +++ b/tests/com.archimatetool.model.tests/src/com/archimatetool/model/impl/DiagramModelObjectTests.java @@ -159,6 +159,13 @@ public void testGetLineColor() { assertEquals("#ffffff", object.getLineColor()); } + @Test + public void testGetLineStyle() { + assertEquals(0, object.getLineStyle()); + object.setLineStyle(1); + assertEquals(1, object.getLineStyle()); + } + @Test public void testAddConnection_Null_ThrowsException() { assertThrows(IllegalArgumentException.class, () -> {