1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.modeling.ui.preferences;
\r
14 import java.text.DecimalFormat;
\r
15 import java.text.ParseException;
\r
17 import org.eclipse.core.runtime.preferences.InstanceScope;
\r
18 import org.eclipse.jface.layout.GridDataFactory;
\r
19 import org.eclipse.jface.layout.GridLayoutFactory;
\r
20 import org.eclipse.jface.preference.BooleanFieldEditor;
\r
21 import org.eclipse.jface.preference.FieldEditor;
\r
22 import org.eclipse.jface.preference.FieldEditorPreferencePage;
\r
23 import org.eclipse.jface.preference.IPreferenceStore;
\r
24 import org.eclipse.swt.SWT;
\r
25 import org.eclipse.swt.events.DisposeEvent;
\r
26 import org.eclipse.swt.events.DisposeListener;
\r
27 import org.eclipse.swt.events.PaintEvent;
\r
28 import org.eclipse.swt.events.PaintListener;
\r
29 import org.eclipse.swt.graphics.GC;
\r
30 import org.eclipse.swt.graphics.Point;
\r
31 import org.eclipse.swt.layout.GridData;
\r
32 import org.eclipse.swt.widgets.Button;
\r
33 import org.eclipse.swt.widgets.Canvas;
\r
34 import org.eclipse.swt.widgets.Combo;
\r
35 import org.eclipse.swt.widgets.Composite;
\r
36 import org.eclipse.swt.widgets.Event;
\r
37 import org.eclipse.swt.widgets.Group;
\r
38 import org.eclipse.swt.widgets.Label;
\r
39 import org.eclipse.swt.widgets.Listener;
\r
40 import org.eclipse.swt.widgets.Text;
\r
41 import org.eclipse.ui.IWorkbench;
\r
42 import org.eclipse.ui.IWorkbenchPreferencePage;
\r
43 import org.eclipse.ui.preferences.ScopedPreferenceStore;
\r
44 import org.osgi.service.prefs.BackingStoreException;
\r
45 import org.simantics.modeling.ui.Activator;
\r
46 import org.simantics.ui.workbench.preferences.NumberFieldEditor;
\r
47 import org.simantics.utils.page.MarginUtils.Margin;
\r
48 import org.simantics.utils.page.MarginUtils.Margins;
\r
49 import org.simantics.utils.page.PageDesc;
\r
50 import org.simantics.utils.page.PageOrientation;
\r
51 import org.simantics.utils.ui.ErrorLogger;
\r
53 public class DiagramPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
\r
55 public DiagramPreferencePage() {
\r
60 public void init(IWorkbench workbench) {
\r
64 protected IPreferenceStore doGetPreferenceStore() {
\r
65 return new ScopedPreferenceStore(InstanceScope.INSTANCE, Activator.PLUGIN_ID);
\r
69 protected void createFieldEditors() {
\r
70 Group group = new Group(getFieldEditorParent(), SWT.NONE);
\r
71 group.setText("Grid Snapping");
\r
72 GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(group);
\r
74 NumberFieldEditor gridSizeField = new NumberFieldEditor(DiagramPreferences.P_SNAP_GRID_SIZE, "Grid size (mm)", group);
\r
75 // 1um - 1m grid size allowed
\r
76 gridSizeField.setValidRange(1e-3, 1e3);
\r
77 addField(gridSizeField);
\r
79 GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(group);
\r
81 PageDescFieldEditor pageDescField = new PageDescFieldEditor(getFieldEditorParent());
\r
82 addField(pageDescField);
\r
84 Group displayGroup = new Group(getFieldEditorParent(), SWT.NONE);
\r
85 displayGroup.setText("Display");
\r
86 GridDataFactory.fillDefaults().grab(true, false).span(1, 1).applyTo(displayGroup);
\r
88 BooleanFieldEditor displayPage = new BooleanFieldEditor(DiagramPreferences.P_DISPLAY_PAGE_SIZE, "Show page borders", BooleanFieldEditor.SEPARATE_LABEL, displayGroup);
\r
89 addField(displayPage);
\r
90 BooleanFieldEditor displayMargins = new BooleanFieldEditor(DiagramPreferences.P_DISPLAY_MARGINS, "Show margins", BooleanFieldEditor.SEPARATE_LABEL, displayGroup);
\r
91 addField(displayMargins);
\r
93 GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(displayGroup);
\r
96 static class PageDescFieldEditor extends FieldEditor {
\r
99 PageDesc previousDesc;
\r
114 Listener marginListener = new Listener() {
\r
116 public void handleEvent(Event event) {
\r
117 if (event.type == SWT.Modify) {
\r
118 Text txt = (Text) event.widget;
\r
119 String s = txt.getText();
\r
121 boolean invalid = false;
\r
123 value = DecimalFormat.getInstance().parse(s).doubleValue();
\r
124 } catch (ParseException e) {
\r
128 txt.setBackground(txt.getDisplay().getSystemColor(SWT.COLOR_RED));
\r
130 txt.setBackground(null);
\r
131 int mask = txt == topMargin ? Margins.TOP : txt == leftMargin ? Margins.LEFT
\r
132 : txt == rightMargin ? Margins.RIGHT : txt == bottomMargin ? Margins.BOTTOM : 0;
\r
133 Margin m = new Margin(0, 0, value);
\r
134 desc = desc.withMargins(desc.getMargins().withSide(mask, m));
\r
135 applyValuesToWidgets(false);
\r
137 } else if (event.type == SWT.FocusIn) {
\r
138 Text txt = (Text) event.widget;
\r
144 int[] marginEvents = { SWT.Modify, SWT.FocusIn };
\r
146 private void addMarginListeners() {
\r
147 for (int et : marginEvents) {
\r
148 topMargin.addListener(et, marginListener);
\r
149 leftMargin.addListener(et, marginListener);
\r
150 rightMargin.addListener(et, marginListener);
\r
151 bottomMargin.addListener(et, marginListener);
\r
155 private void removeMarginListeners() {
\r
156 for (int et : marginEvents) {
\r
157 topMargin.removeListener(et, marginListener);
\r
158 leftMargin.removeListener(et, marginListener);
\r
159 rightMargin.removeListener(et, marginListener);
\r
160 bottomMargin.removeListener(et, marginListener);
\r
164 public PageDescFieldEditor(Composite parent) {
\r
165 DiagramPreferences prefs = DiagramPreferenceUtil.getPreferences();
\r
166 desc = prefs.get(DiagramPreferences.P_DEFAULT_PAGE_SIZE);
\r
167 previousDesc = desc;
\r
169 createControl(parent);
\r
173 protected void adjustForNumColumns(int numColumns) {
\r
174 if (group != null) {
\r
175 ((GridData) group.getLayoutData()).horizontalSpan = numColumns;
\r
180 protected void doFillIntoGrid(Composite parent, int numColumns) {
\r
181 group = getGroupControl(parent);
\r
182 GridDataFactory.fillDefaults().grab(true, false).span(numColumns, 1).applyTo(group);
\r
186 * Returns the change button for this field editor.
\r
187 * @param parent The Composite to create the receiver in.
\r
189 * @return the change button
\r
191 protected Group getGroupControl(Composite parent) {
\r
192 if (group == null) {
\r
193 group = new Group(parent, SWT.NONE);
\r
194 group.setText("Page Defaults");
\r
195 group.setToolTipText("The default settings for diagram pages.");
\r
196 group.setFont(parent.getFont());
\r
197 group.addDisposeListener(new DisposeListener() {
\r
198 public void widgetDisposed(DisposeEvent event) {
\r
202 GridLayoutFactory.fillDefaults().numColumns(3).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(group);
\r
203 createChoosers(group);
\r
205 checkParent(group, parent);
\r
210 protected void createChoosers(Composite parent) {
\r
211 //parent.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_BLUE));
\r
212 Label label = new Label(parent, 0);
\r
213 label.setText("Size:");
\r
214 combo = new Combo(parent, 0);
\r
215 combo.addListener(SWT.Selection, new Listener() {
\r
217 public void handleEvent(Event event) {
\r
218 PageDesc pd = (PageDesc) combo.getData(combo.getItem(combo.getSelectionIndex()));
\r
220 desc = desc.withSizeFrom(pd).withText(pd.getText());
\r
221 applyValuesToWidgets();
\r
226 Composite marginComposite = new Composite(parent, 0);
\r
227 //marginComposite.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_RED));
\r
228 GridDataFactory.fillDefaults().grab(true, true).grab(true, true).align(SWT.CENTER, SWT.CENTER).span(1, 2).applyTo(marginComposite);
\r
229 GridLayoutFactory.fillDefaults().numColumns(3).margins(5, 5).spacing(3, 3).applyTo(marginComposite);
\r
230 label = new Label(marginComposite, 0);
\r
231 label.setText("Margins (mm)");
\r
233 GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.TOP).span(3, 1).applyTo(label);
\r
234 label = new Label(marginComposite, 0);
\r
235 GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.TOP).span(3, 1).applyTo(label);
\r
236 new Label(marginComposite, 0);
\r
237 topMargin = new Text(marginComposite, SWT.BORDER | SWT.CENTER);
\r
238 GridDataFactory.fillDefaults().hint(50, SWT.DEFAULT).grab(true, false).applyTo(topMargin);
\r
239 new Label(marginComposite, 0);
\r
240 leftMargin = new Text(marginComposite, SWT.BORDER | SWT.RIGHT);
\r
241 GridDataFactory.swtDefaults().hint(50, SWT.DEFAULT).grab(true, false).applyTo(leftMargin);
\r
242 pageCanvas = new Canvas(marginComposite, 0);
\r
243 GridDataFactory.swtDefaults().hint(SWT.DEFAULT, SWT.DEFAULT).grab(true, true).applyTo(pageCanvas);
\r
244 pageCanvas.addPaintListener(new PaintListener() {
\r
246 public void paintControl(PaintEvent e) {
\r
248 Point size = pageCanvas.getSize();
\r
250 double w = desc.getOrientedWidth();
\r
251 double h = desc.getOrientedHeight();
\r
253 Margins margins = desc.getMargins();
\r
254 int top = (int) Math.round(size.y * margins.top.diagramAbsolute / h);
\r
255 int bottom = (int) Math.round(size.y * margins.bottom.diagramAbsolute / h);
\r
256 int left = (int) Math.round(size.x * margins.left.diagramAbsolute / w);
\r
257 int right = (int) Math.round(size.x * margins.right.diagramAbsolute / w);
\r
259 gc.setBackground(gc.getDevice().getSystemColor(SWT.COLOR_GRAY));
\r
260 gc.fillRectangle(0, 0, size.x, size.y);
\r
262 if ((top+bottom) < size.y && (left+right) < size.x) {
\r
263 gc.drawLine(left, 0, left, size.y-1);
\r
264 gc.drawLine(size.x-1-right, 0, size.x-1-right, size.y-1);
\r
265 gc.drawLine(0, top, size.x-1, top);
\r
266 gc.drawLine(0, size.y-1-bottom, size.x-1, size.y-1-bottom);
\r
268 gc.setBackground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
\r
269 gc.fillRectangle(left+1, top+1, size.x-2-right-left, size.y-2-top-bottom);
\r
273 rightMargin = new Text(marginComposite, SWT.BORDER | SWT.LEFT);
\r
274 GridDataFactory.swtDefaults().hint(50, SWT.DEFAULT).grab(true, false).applyTo(rightMargin);
\r
275 new Label(marginComposite, 0);
\r
276 bottomMargin = new Text(marginComposite, SWT.BORDER | SWT.CENTER);
\r
277 GridDataFactory.fillDefaults().hint(50, SWT.DEFAULT).grab(true, false).applyTo(bottomMargin);
\r
278 new Label(marginComposite, 0);
\r
280 addMarginListeners();
\r
282 label = new Label(parent, 0);
\r
283 label.setText("Orientation:");
\r
284 Composite comp = new Composite(parent, 0);
\r
285 GridDataFactory.fillDefaults().span(1, 1).align(SWT.LEFT, SWT.CENTER).applyTo(comp);
\r
286 GridLayoutFactory.fillDefaults().numColumns(1).applyTo(comp);
\r
287 portrait = new Button(comp, SWT.RADIO);
\r
288 landscape = new Button(comp, SWT.RADIO);
\r
289 portrait.setText("Portrait");
\r
290 landscape.setText("Landscape");
\r
292 Listener orientationListener = new Listener() {
\r
294 public void handleEvent(Event event) {
\r
295 if (portrait.getSelection())
\r
296 desc = desc.withOrientation(PageOrientation.Portrait);
\r
298 desc = desc.withOrientation(PageOrientation.Landscape);
\r
300 applyValuesToWidgets();
\r
303 portrait.addListener(SWT.Selection, orientationListener);
\r
304 landscape.addListener(SWT.Selection, orientationListener);
\r
306 PageDesc[] pds = PageDesc.getPredefinedDescriptions();
\r
307 for (int i = 0; i < pds.length; ++i) {
\r
308 PageDesc pd = pds[i];
\r
309 combo.add(pd.getText());
\r
310 combo.setData(pd.getText(), pd);
\r
313 applyValuesToWidgets();
\r
317 protected void doLoad() {
\r
318 if (group != null) {
\r
319 DiagramPreferences prefs = DiagramPreferenceUtil.getPreferences();
\r
321 desc = prefs.get(DiagramPreferences.P_DEFAULT_PAGE_SIZE);
\r
322 previousDesc = desc;
\r
324 applyValuesToWidgets();
\r
328 private void applyValuesToWidgets() {
\r
329 applyValuesToWidgets(true);
\r
332 private void applyValuesToWidgets(boolean applyMargins) {
\r
333 PageOrientation orit = desc.getOrientation();
\r
334 portrait.setSelection( orit == PageOrientation.Portrait );
\r
335 landscape.setSelection( orit == PageOrientation.Landscape );
\r
336 String name = desc.getText();
\r
337 int selectedIndex = combo.getSelectionIndex();
\r
338 for (int i = 0; i < combo.getItemCount(); ++i) {
\r
339 String item = combo.getItem(i);
\r
340 if (name.equals(item)) {
\r
341 if (selectedIndex != i) {
\r
348 if (applyMargins) {
\r
349 boolean marginEnabled = !desc.isInfinite();
\r
350 topMargin.setEnabled(marginEnabled);
\r
351 leftMargin.setEnabled(marginEnabled);
\r
352 rightMargin.setEnabled(marginEnabled);
\r
353 bottomMargin.setEnabled(marginEnabled);
\r
355 if (marginEnabled) {
\r
356 removeMarginListeners();
\r
357 Margins margins = desc.getMargins();
\r
358 topMargin.setText(DecimalFormat.getNumberInstance().format(margins.top.diagramAbsolute));
\r
359 leftMargin.setText(DecimalFormat.getNumberInstance().format(margins.left.diagramAbsolute));
\r
360 rightMargin.setText(DecimalFormat.getNumberInstance().format(margins.right.diagramAbsolute));
\r
361 bottomMargin.setText(DecimalFormat.getNumberInstance().format(margins.bottom.diagramAbsolute));
\r
362 addMarginListeners();
\r
369 void layout(PageDesc desc) {
\r
370 double max = Math.max(desc.getOrientedWidth(), desc.getOrientedHeight());
\r
371 double min = Math.min(desc.getOrientedWidth(), desc.getOrientedHeight());
\r
372 double ratio = min / max;
\r
374 int smaller = (int) Math.round(ratio*larger);
\r
376 boolean vertical = desc.getOrientedWidth() < desc.getOrientedHeight();
\r
378 GridData gd = (GridData) pageCanvas.getLayoutData();
\r
379 gd.widthHint = vertical ? smaller : larger;
\r
380 gd.heightHint = vertical ? larger : smaller;
\r
382 group.getParent().layout(true, true);
\r
383 pageCanvas.redraw();
\r
387 protected void doLoadDefault() {
\r
388 if (group != null) {
\r
389 DiagramPreferences prefs = DiagramPreferenceUtil.getDefaultPreferences();
\r
390 desc = prefs.get(DiagramPreferences.P_DEFAULT_PAGE_SIZE);
\r
391 previousDesc = desc;
\r
393 applyValuesToWidgets();
\r
395 // This is a workaround for a problem of not having a single preference backing this CommonsFieldEditor
\r
396 setPresentsDefaultValue(false);
\r
400 protected void doStore() {
\r
402 DiagramPreferenceUtil.flushPreferences(DiagramPreferenceUtil.getPreferences().withValue(DiagramPreferences.P_DEFAULT_PAGE_SIZE, desc));
\r
403 } catch (BackingStoreException e) {
\r
404 ErrorLogger.defaultLogError("Could not store diagram preferences", e);
\r
409 public int getNumberOfControls() {
\r