1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.modeling.ui.preferences;
14 import java.text.DecimalFormat;
15 import java.text.ParseException;
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;
53 public class DiagramPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
55 public DiagramPreferencePage() {
60 public void init(IWorkbench workbench) {
64 protected IPreferenceStore doGetPreferenceStore() {
65 return new ScopedPreferenceStore(InstanceScope.INSTANCE, Activator.PLUGIN_ID);
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);
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);
79 GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(group);
81 PageDescFieldEditor pageDescField = new PageDescFieldEditor(getFieldEditorParent());
82 addField(pageDescField);
84 Group displayGroup = new Group(getFieldEditorParent(), SWT.NONE);
85 displayGroup.setText("Display");
86 GridDataFactory.fillDefaults().grab(true, false).span(1, 1).applyTo(displayGroup);
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);
93 GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(displayGroup);
96 static class PageDescFieldEditor extends FieldEditor {
99 PageDesc previousDesc;
114 Listener marginListener = new Listener() {
116 public void handleEvent(Event event) {
117 if (event.type == SWT.Modify) {
118 Text txt = (Text) event.widget;
119 String s = txt.getText();
121 boolean invalid = false;
123 value = DecimalFormat.getInstance().parse(s).doubleValue();
124 } catch (ParseException e) {
128 txt.setBackground(txt.getDisplay().getSystemColor(SWT.COLOR_RED));
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);
137 } else if (event.type == SWT.FocusIn) {
138 Text txt = (Text) event.widget;
144 int[] marginEvents = { SWT.Modify, SWT.FocusIn };
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);
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);
164 public PageDescFieldEditor(Composite parent) {
165 DiagramPreferences prefs = DiagramPreferenceUtil.getPreferences();
166 desc = prefs.get(DiagramPreferences.P_DEFAULT_PAGE_SIZE);
169 createControl(parent);
173 protected void adjustForNumColumns(int numColumns) {
175 ((GridData) group.getLayoutData()).horizontalSpan = numColumns;
180 protected void doFillIntoGrid(Composite parent, int numColumns) {
181 group = getGroupControl(parent);
182 GridDataFactory.fillDefaults().grab(true, false).span(numColumns, 1).applyTo(group);
186 * Returns the change button for this field editor.
187 * @param parent The Composite to create the receiver in.
189 * @return the change button
191 protected Group getGroupControl(Composite parent) {
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) {
202 GridLayoutFactory.fillDefaults().numColumns(3).equalWidth(false).extendedMargins(12, 12, 12, 12).spacing(5, 4).applyTo(group);
203 createChoosers(group);
205 checkParent(group, parent);
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() {
217 public void handleEvent(Event event) {
218 PageDesc pd = (PageDesc) combo.getData(combo.getItem(combo.getSelectionIndex()));
220 desc = desc.withSizeFrom(pd).withText(pd.getText());
221 applyValuesToWidgets();
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)");
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() {
246 public void paintControl(PaintEvent e) {
248 Point size = pageCanvas.getSize();
250 double w = desc.getOrientedWidth();
251 double h = desc.getOrientedHeight();
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);
259 gc.setBackground(gc.getDevice().getSystemColor(SWT.COLOR_GRAY));
260 gc.fillRectangle(0, 0, size.x, size.y);
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);
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);
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);
280 addMarginListeners();
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");
292 Listener orientationListener = new Listener() {
294 public void handleEvent(Event event) {
295 if (portrait.getSelection())
296 desc = desc.withOrientation(PageOrientation.Portrait);
298 desc = desc.withOrientation(PageOrientation.Landscape);
300 applyValuesToWidgets();
303 portrait.addListener(SWT.Selection, orientationListener);
304 landscape.addListener(SWT.Selection, orientationListener);
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);
313 applyValuesToWidgets();
317 protected void doLoad() {
319 DiagramPreferences prefs = DiagramPreferenceUtil.getPreferences();
321 desc = prefs.get(DiagramPreferences.P_DEFAULT_PAGE_SIZE);
324 applyValuesToWidgets();
328 private void applyValuesToWidgets() {
329 applyValuesToWidgets(true);
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) {
349 boolean marginEnabled = !desc.isInfinite();
350 topMargin.setEnabled(marginEnabled);
351 leftMargin.setEnabled(marginEnabled);
352 rightMargin.setEnabled(marginEnabled);
353 bottomMargin.setEnabled(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();
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;
374 int smaller = (int) Math.round(ratio*larger);
376 boolean vertical = desc.getOrientedWidth() < desc.getOrientedHeight();
378 GridData gd = (GridData) pageCanvas.getLayoutData();
379 gd.widthHint = vertical ? smaller : larger;
380 gd.heightHint = vertical ? larger : smaller;
382 group.getParent().layout(true, true);
387 protected void doLoadDefault() {
389 DiagramPreferences prefs = DiagramPreferenceUtil.getDefaultPreferences();
390 desc = prefs.get(DiagramPreferences.P_DEFAULT_PAGE_SIZE);
393 applyValuesToWidgets();
395 // This is a workaround for a problem of not having a single preference backing this CommonsFieldEditor
396 setPresentsDefaultValue(false);
400 protected void doStore() {
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);
409 public int getNumberOfControls() {