]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/preferences/DiagramPreferencePage.java
Improved usability of shared library export wizard
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / preferences / DiagramPreferencePage.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.modeling.ui.preferences;
13
14 import java.text.DecimalFormat;
15 import java.text.ParseException;
16
17 import org.eclipse.core.runtime.preferences.InstanceScope;
18 import org.eclipse.jface.layout.GridDataFactory;
19 import org.eclipse.jface.layout.GridLayoutFactory;
20 import org.eclipse.jface.preference.BooleanFieldEditor;
21 import org.eclipse.jface.preference.FieldEditor;
22 import org.eclipse.jface.preference.FieldEditorPreferencePage;
23 import org.eclipse.jface.preference.IPreferenceStore;
24 import org.eclipse.swt.SWT;
25 import org.eclipse.swt.events.DisposeEvent;
26 import org.eclipse.swt.events.DisposeListener;
27 import org.eclipse.swt.events.PaintEvent;
28 import org.eclipse.swt.events.PaintListener;
29 import org.eclipse.swt.graphics.GC;
30 import org.eclipse.swt.graphics.Point;
31 import org.eclipse.swt.layout.GridData;
32 import org.eclipse.swt.widgets.Button;
33 import org.eclipse.swt.widgets.Canvas;
34 import org.eclipse.swt.widgets.Combo;
35 import org.eclipse.swt.widgets.Composite;
36 import org.eclipse.swt.widgets.Event;
37 import org.eclipse.swt.widgets.Group;
38 import org.eclipse.swt.widgets.Label;
39 import org.eclipse.swt.widgets.Listener;
40 import org.eclipse.swt.widgets.Text;
41 import org.eclipse.ui.IWorkbench;
42 import org.eclipse.ui.IWorkbenchPreferencePage;
43 import org.eclipse.ui.preferences.ScopedPreferenceStore;
44 import org.osgi.service.prefs.BackingStoreException;
45 import org.simantics.modeling.ui.Activator;
46 import org.simantics.ui.workbench.preferences.NumberFieldEditor;
47 import org.simantics.utils.page.MarginUtils.Margin;
48 import org.simantics.utils.page.MarginUtils.Margins;
49 import org.simantics.utils.page.PageDesc;
50 import org.simantics.utils.page.PageOrientation;
51 import org.simantics.utils.ui.ErrorLogger;
52
53 public class DiagramPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
54
55     public DiagramPreferencePage() {
56         super(GRID);
57     }
58
59     @Override
60     public void init(IWorkbench workbench) {
61     }
62
63     @Override
64     protected IPreferenceStore doGetPreferenceStore() {
65         return new ScopedPreferenceStore(InstanceScope.INSTANCE, Activator.PLUGIN_ID);
66     }
67
68     @Override
69     protected void createFieldEditors() {
70         Group group = new Group(getFieldEditorParent(), SWT.NONE);
71         group.setText("Grid Snapping");
72         GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(group);
73
74         NumberFieldEditor gridSizeField = new NumberFieldEditor(DiagramPreferences.P_SNAP_GRID_SIZE, "Grid size (mm)", group);
75         // 1um - 1m grid size allowed
76         gridSizeField.setValidRange(1e-3, 1e3);
77         addField(gridSizeField);
78
79         GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(group);
80
81         PageDescFieldEditor pageDescField = new PageDescFieldEditor(getFieldEditorParent());
82         addField(pageDescField);
83
84         Group displayGroup = new Group(getFieldEditorParent(), SWT.NONE);
85         displayGroup.setText("Display");
86         GridDataFactory.fillDefaults().grab(true, false).span(1, 1).applyTo(displayGroup);
87
88         BooleanFieldEditor displayPage = new BooleanFieldEditor(DiagramPreferences.P_DISPLAY_PAGE_SIZE, "Show page borders", BooleanFieldEditor.SEPARATE_LABEL, displayGroup);
89         addField(displayPage);
90         BooleanFieldEditor displayMargins = new BooleanFieldEditor(DiagramPreferences.P_DISPLAY_MARGINS, "Show margins", BooleanFieldEditor.SEPARATE_LABEL, displayGroup);
91         addField(displayMargins);
92
93         GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(displayGroup);
94     }
95
96     static class PageDescFieldEditor extends FieldEditor {
97
98         PageDesc desc;
99         PageDesc previousDesc;
100
101         Group group;
102
103         Button portrait;
104         Button landscape;
105         Combo combo;
106
107         Text topMargin;
108         Text leftMargin;
109         Text rightMargin;
110         Text bottomMargin;
111
112         Canvas pageCanvas;
113
114         Listener marginListener = new Listener() {
115             @Override
116             public void handleEvent(Event event) {
117                 if (event.type == SWT.Modify) {
118                     Text txt = (Text) event.widget;
119                     String s = txt.getText();
120                     double value = 0;
121                     boolean invalid = false;
122                     try {
123                         value = DecimalFormat.getInstance().parse(s).doubleValue();
124                     } catch (ParseException e) {
125                         invalid = true;
126                     }
127                     if (invalid) {
128                         txt.setBackground(txt.getDisplay().getSystemColor(SWT.COLOR_RED));
129                     } else {
130                         txt.setBackground(null);
131                         int mask = txt == topMargin ? Margins.TOP : txt == leftMargin ? Margins.LEFT
132                                 : txt == rightMargin ? Margins.RIGHT : txt == bottomMargin ? Margins.BOTTOM : 0;
133                         Margin m = new Margin(0, 0, value);
134                         desc = desc.withMargins(desc.getMargins().withSide(mask, m));
135                         applyValuesToWidgets(false);
136                     }
137                 } else if (event.type == SWT.FocusIn) {
138                     Text txt = (Text) event.widget;
139                     txt.selectAll();
140                 }
141             }
142         };
143
144         int[] marginEvents = { SWT.Modify, SWT.FocusIn };
145
146         private void addMarginListeners() {
147             for (int et : marginEvents) {
148                 topMargin.addListener(et, marginListener);
149                 leftMargin.addListener(et, marginListener);
150                 rightMargin.addListener(et, marginListener);
151                 bottomMargin.addListener(et, marginListener);
152             }
153         }
154
155         private void removeMarginListeners() {
156             for (int et : marginEvents) {
157                 topMargin.removeListener(et, marginListener);
158                 leftMargin.removeListener(et, marginListener);
159                 rightMargin.removeListener(et, marginListener);
160                 bottomMargin.removeListener(et, marginListener);
161             }
162         }
163
164         public PageDescFieldEditor(Composite parent) {
165             DiagramPreferences prefs = DiagramPreferenceUtil.getPreferences();
166             desc = prefs.get(DiagramPreferences.P_DEFAULT_PAGE_SIZE);
167             previousDesc = desc;
168
169             createControl(parent);
170         }
171
172         @Override
173         protected void adjustForNumColumns(int numColumns) {
174             if (group != null) {
175                 ((GridData) group.getLayoutData()).horizontalSpan = numColumns;
176             }
177         }
178
179         @Override
180         protected void doFillIntoGrid(Composite parent, int numColumns) {
181             group = getGroupControl(parent);
182             GridDataFactory.fillDefaults().grab(true, false).span(numColumns, 1).applyTo(group);
183         }
184
185         /**
186          * Returns the change button for this field editor.
187          * @param parent The Composite to create the receiver in.
188          *
189          * @return the change button
190          */
191         protected Group getGroupControl(Composite parent) {
192             if (group == null) {
193                 group = new Group(parent, SWT.NONE);
194                 group.setText("Page Defaults");
195                 group.setToolTipText("The default settings for diagram pages.");
196                 group.setFont(parent.getFont());
197                 group.addDisposeListener(new DisposeListener() {
198                     public void widgetDisposed(DisposeEvent event) {
199                         group = null;
200                     }
201                 });
202                 GridLayoutFactory.fillDefaults().numColumns(3).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(group);
203                 createChoosers(group);
204             } else {
205                 checkParent(group, parent);
206             }
207             return group;
208         }
209
210         protected void createChoosers(Composite parent) {
211             //parent.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_BLUE));
212             Label label = new Label(parent, 0);
213             label.setText("Size:");
214             combo = new Combo(parent, 0);
215             combo.addListener(SWT.Selection, new Listener() {
216                 @Override
217                 public void handleEvent(Event event) {
218                     PageDesc pd = (PageDesc) combo.getData(combo.getItem(combo.getSelectionIndex()));
219                     if (pd != null) {
220                         desc = desc.withSizeFrom(pd).withText(pd.getText());
221                         applyValuesToWidgets();
222                     }
223                 }
224             });
225
226             Composite marginComposite = new Composite(parent, 0);
227             //marginComposite.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_RED));
228             GridDataFactory.fillDefaults().grab(true, true).grab(true, true).align(SWT.CENTER, SWT.CENTER).span(1, 2).applyTo(marginComposite);
229             GridLayoutFactory.fillDefaults().numColumns(3).margins(5, 5).spacing(3, 3).applyTo(marginComposite);
230             label = new Label(marginComposite, 0);
231             label.setText("Margins (mm)");
232
233             GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.TOP).span(3, 1).applyTo(label);
234             label = new Label(marginComposite, 0);
235             GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.TOP).span(3, 1).applyTo(label);
236             new Label(marginComposite, 0);
237             topMargin = new Text(marginComposite, SWT.BORDER | SWT.CENTER);
238             GridDataFactory.fillDefaults().hint(50, SWT.DEFAULT).grab(true, false).applyTo(topMargin);
239             new Label(marginComposite, 0);
240             leftMargin = new Text(marginComposite, SWT.BORDER | SWT.RIGHT);
241             GridDataFactory.swtDefaults().hint(50, SWT.DEFAULT).grab(true, false).applyTo(leftMargin);
242             pageCanvas = new Canvas(marginComposite, 0);
243             GridDataFactory.swtDefaults().hint(SWT.DEFAULT, SWT.DEFAULT).grab(true, true).applyTo(pageCanvas);
244             pageCanvas.addPaintListener(new PaintListener() {
245                 @Override
246                 public void paintControl(PaintEvent e) {
247                     GC gc = e.gc;
248                     Point size = pageCanvas.getSize();
249
250                     double w = desc.getOrientedWidth();
251                     double h = desc.getOrientedHeight();
252
253                     Margins margins = desc.getMargins();
254                     int top = (int) Math.round(size.y * margins.top.diagramAbsolute / h);
255                     int bottom = (int) Math.round(size.y * margins.bottom.diagramAbsolute / h);
256                     int left = (int) Math.round(size.x * margins.left.diagramAbsolute / w);
257                     int right = (int) Math.round(size.x * margins.right.diagramAbsolute / w);
258
259                     gc.setBackground(gc.getDevice().getSystemColor(SWT.COLOR_GRAY));
260                     gc.fillRectangle(0, 0, size.x, size.y);
261
262                     if ((top+bottom) < size.y && (left+right) < size.x) {
263                         gc.drawLine(left, 0, left, size.y-1);
264                         gc.drawLine(size.x-1-right, 0, size.x-1-right, size.y-1);
265                         gc.drawLine(0, top, size.x-1, top);
266                         gc.drawLine(0, size.y-1-bottom, size.x-1, size.y-1-bottom);
267
268                         gc.setBackground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
269                         gc.fillRectangle(left+1, top+1, size.x-2-right-left, size.y-2-top-bottom);
270                     }
271                 }
272             });
273             rightMargin = new Text(marginComposite, SWT.BORDER | SWT.LEFT);
274             GridDataFactory.swtDefaults().hint(50, SWT.DEFAULT).grab(true, false).applyTo(rightMargin);
275             new Label(marginComposite, 0);
276             bottomMargin = new Text(marginComposite, SWT.BORDER | SWT.CENTER);
277             GridDataFactory.fillDefaults().hint(50, SWT.DEFAULT).grab(true, false).applyTo(bottomMargin);
278             new Label(marginComposite, 0);
279
280             addMarginListeners();
281
282             label = new Label(parent, 0);
283             label.setText("Orientation:");
284             Composite comp = new Composite(parent, 0);
285             GridDataFactory.fillDefaults().span(1, 1).align(SWT.LEFT, SWT.CENTER).applyTo(comp);
286             GridLayoutFactory.fillDefaults().numColumns(1).applyTo(comp);
287             portrait = new Button(comp, SWT.RADIO);
288             landscape = new Button(comp, SWT.RADIO);
289             portrait.setText("Portrait");
290             landscape.setText("Landscape");
291
292             Listener orientationListener = new Listener() {
293                 @Override
294                 public void handleEvent(Event event) {
295                     if (portrait.getSelection())
296                         desc = desc.withOrientation(PageOrientation.Portrait);
297                     else
298                         desc = desc.withOrientation(PageOrientation.Landscape);
299
300                     applyValuesToWidgets();
301                 }
302             };
303             portrait.addListener(SWT.Selection, orientationListener);
304             landscape.addListener(SWT.Selection, orientationListener);
305
306             PageDesc[] pds = PageDesc.getPredefinedDescriptions();
307             for (int i = 0; i < pds.length; ++i) {
308                 PageDesc pd = pds[i];
309                 combo.add(pd.getText());
310                 combo.setData(pd.getText(), pd);
311             }
312
313             applyValuesToWidgets();
314         }
315
316         @Override
317         protected void doLoad() {
318             if (group != null) {
319                 DiagramPreferences prefs = DiagramPreferenceUtil.getPreferences();
320
321                 desc = prefs.get(DiagramPreferences.P_DEFAULT_PAGE_SIZE);
322                 previousDesc = desc;
323
324                 applyValuesToWidgets();
325             }
326         }
327
328         private void applyValuesToWidgets() {
329             applyValuesToWidgets(true);
330         }
331
332         private void applyValuesToWidgets(boolean applyMargins) {
333                 PageOrientation orit = desc.getOrientation();
334             portrait.setSelection( orit == PageOrientation.Portrait );
335             landscape.setSelection(  orit == PageOrientation.Landscape );
336             String name = desc.getText();
337             int selectedIndex = combo.getSelectionIndex();
338             for (int i = 0; i < combo.getItemCount(); ++i) {
339                 String item = combo.getItem(i);
340                 if (name.equals(item)) {
341                     if (selectedIndex != i) {
342                         combo.select(i);
343                     }
344                     break;
345                 }
346             }
347
348             if (applyMargins) {
349                 boolean marginEnabled = !desc.isInfinite();
350                 topMargin.setEnabled(marginEnabled);
351                 leftMargin.setEnabled(marginEnabled);
352                 rightMargin.setEnabled(marginEnabled);
353                 bottomMargin.setEnabled(marginEnabled);
354
355                 if (marginEnabled) {
356                     removeMarginListeners();
357                     Margins margins = desc.getMargins();
358                     topMargin.setText(DecimalFormat.getNumberInstance().format(margins.top.diagramAbsolute));
359                     leftMargin.setText(DecimalFormat.getNumberInstance().format(margins.left.diagramAbsolute));
360                     rightMargin.setText(DecimalFormat.getNumberInstance().format(margins.right.diagramAbsolute));
361                     bottomMargin.setText(DecimalFormat.getNumberInstance().format(margins.bottom.diagramAbsolute));
362                     addMarginListeners();
363                 }
364             }
365
366             layout(desc);
367         }
368
369         void layout(PageDesc desc) {
370             double max = Math.max(desc.getOrientedWidth(), desc.getOrientedHeight());
371             double min = Math.min(desc.getOrientedWidth(), desc.getOrientedHeight());
372             double ratio = min / max;
373             int larger = 100;
374             int smaller = (int) Math.round(ratio*larger);
375
376             boolean vertical = desc.getOrientedWidth() < desc.getOrientedHeight();
377
378             GridData gd = (GridData) pageCanvas.getLayoutData();
379             gd.widthHint = vertical ? smaller : larger;
380             gd.heightHint = vertical ? larger : smaller;
381
382             group.getParent().layout(true, true);
383             pageCanvas.redraw();
384         }
385
386         @Override
387         protected void doLoadDefault() {
388             if (group != null) {
389                 DiagramPreferences prefs = DiagramPreferenceUtil.getDefaultPreferences();
390                 desc = prefs.get(DiagramPreferences.P_DEFAULT_PAGE_SIZE);
391                 previousDesc = desc;
392
393                 applyValuesToWidgets();
394             }
395             // This is a workaround for a problem of not having a single preference backing this CommonsFieldEditor
396             setPresentsDefaultValue(false);
397         }
398
399         @Override
400         protected void doStore() {
401             try {
402                 DiagramPreferenceUtil.flushPreferences(DiagramPreferenceUtil.getPreferences().withValue(DiagramPreferences.P_DEFAULT_PAGE_SIZE, desc));
403             } catch (BackingStoreException e) {
404                 ErrorLogger.defaultLogError("Could not store diagram preferences", e);
405             }
406         }
407
408         @Override
409         public int getNumberOfControls() {
410             return 1;
411         }
412     }
413
414 }