001: package net.refractions.udig.style;
002:
003: import net.refractions.udig.project.IBlackboard;
004: import net.refractions.udig.project.internal.Layer;
005:
006: import org.eclipse.jface.action.IAction;
007: import org.eclipse.swt.widgets.Composite;
008: import org.eclipse.ui.IViewSite;
009: import org.eclipse.ui.PartInitException;
010:
011: /**
012: *
013: * Configures a style object.
014: * <p>
015: * Responsibilities:
016: * <ul>
017: * <li>Creating a ui to allow user configuration of a style object.
018: * <li>Placing style object information onto the style blackboard of a layer.
019: * <li>Determining if a style configurator can be used to configure the style
020: * of a particular layer.
021: * </ul>
022: * </p>
023: * <p>
024: * Style objects are stored a StyleBlackboard. Configurators use the blackboard
025: * to collaborate. Objects are stored on the blackboard by id. When a configurator
026: * queries the blackboard for an object and it does not exist, a default object
027: * should be created and placed on the blackboard. The following is an example:
028: * <code>
029: * ...
030: * StyleBlackboard styleBlackboard = getStyleBlackboard();
031: * Point style = styleBlackboard.lookup("point.style");
032: *
033: * if (style == null) {
034: * style = new Point();
035: * style.setX(0);
036: * style.setY(0);
037: * styleBlackboard.put("point.style", style);
038: * }
039: * ...
040: * </code>
041: * </p>
042: * <p>
043: * Each Layer has a StyleBlackboard. Configurators should not write to this
044: * blackboard directly. Each configurator is supplied with a copy of the actual
045: * layer blackboard.
046: * </p>
047: * <p>
048: * <b>Note:</b><i>Each time a style object is changed, it must be replaced onto
049: * the blackboard for persistance reasons.</i>
050: * <code>
051: * StyleBlackboard styleBlackboard = getStyleBlackboard();
052: * Point style = styleBlackboard.lookup("point.style");
053: * ...
054: * style.setX(10);
055: * style.setY(10);
056: *
057: * styleBlackboard.put("point.style", style);
058: * </code>
059: * </p>
060: * <p>
061: * The StyleConfigurator should store no state. All state should be stored in
062: * the style objects on the style blackboard. When a ui widget changes state, the
063: * style object should be written to immediately to reflect the change.
064: * When the configurator becomes active, the ui widgets should be initialized
065: * from the values of style objects on the blackboard. This should be performed
066: * every time refresh() is called.
067: * </p>
068: * <p>
069: * Whenever style objects are read from the blackboard,
070: * </p>
071:
072: * <p>
073: * <code>
074: * void apply() {
075: * StyleBlackboard styleBlackboard = getStyleBlackboard();
076: * Point style = styleBlackboard.lookup("point.style");
077: *
078: * if (style == null) {
079: * style = new Point();
080: * styleBlackboard.put("point.style", style);
081: * }
082: *
083: * style.setX(...) //set to some value from ui
084: * style.setY(...) //set to some value from ui
085: * }
086: *
087: * void init() {
088: * StyleBlackboard styleBlackboard = getStyleBlackboard();
089: * Point style = styleBlackboard.lookup("point.style");
090: * if (style != null) {
091: * //set some ui widget to value of style.getX();
092: * //set some ui widget to value of style.getY();
093: * }
094: * }
095: * </code>
096: * </p>
097: * <p>
098: * A StyleConfigurator is not considered active until its ui has been created.
099: *
100: * </p>
101: * @author Justin Deoliveira
102: * @since 0.6.0
103: *
104: */
105: public abstract class IStyleConfigurator {
106:
107: /** extension point id **/
108: public static final String XPID = "net.refractions.udig.style.styleConfigurator"; //$NON-NLS-1$
109: private String styleId;
110: private String label;
111: private IViewSite site;
112: private Layer layer;
113: private IAction applyAction;
114:
115: /**
116: * Sets the apply action.
117: *
118: * @param applyAction1
119: */
120: public final void setAction(IAction applyAction1) {
121: this .applyAction = applyAction1;
122: }
123:
124: /**
125: * Runs the apply action.
126: */
127: protected void makeActionDoStuff() {
128: if (this .applyAction != null) {
129: this .applyAction.run();
130: }
131: }
132:
133: protected IAction getApplyAction() {
134: return applyAction;
135: }
136:
137: /**
138: * Called after apply action has been triggeredbefore apply is executed.
139: */
140: public void preApply() {
141: //
142: }
143:
144: /**
145: * Returns the declared style id of the style the configurator depends on.
146: * <p>
147: * This is provided by SetStyleId by the extention point.
148: * <p>
149: * <p>
150: * When keeping information associated with a IStyleConfigurator
151: * (in a Map, or Memento) use this as a KEY. Don't use label,
152: * two IStyleConfigurator may have the same label.
153: * </p>
154: * @return styleId The style id.
155: */
156: public final String getStyleId() {
157: return styleId;
158: }
159:
160: /**
161: * Sets the declared style id of the style the configurator depends on.
162: * <p>
163: * Called by the extention point processor.
164: * </p>
165: * @param id The style id.
166: */
167: public final void setStyleId(String id) {
168: this .styleId = id;
169: }
170:
171: /**
172: * Returns the label describing the configurator. Used mainly for ui purposes.
173: *
174: * @return A short description of the configurator.
175: */
176: public final String getLabel() {
177: return label;
178: }
179:
180: /**
181: * Sets the label describing the configurator. Used mainly for ui purposes.
182: *
183: * @param label A short description of the configurator.
184: */
185: public void setLabel(String label) {
186: this .label = label;
187: }
188:
189: /**
190: * Returns the site for this view.
191: * This method is equivalent to <code>(IViewSite) getSite()</code>.
192: * <p>
193: * The site can be <code>null</code> while the view is being initialized.
194: * After the initialization is complete, this value must be non-<code>null</code>
195: * for the remainder of the view's life cycle.
196: * </p>
197: *
198: * @return the view site; this value may be <code>null</code> if the view
199: * has not yet been initialized
200: */
201: public IViewSite getViewSite() {
202: return site;
203: }
204:
205: /**
206: * Initializes this view with the given view site.
207: * <p>
208: * This method is automatically shortly after the part is instantiated.
209: * It marks the start of the views's lifecycle. Clients must not call this
210: * method.
211: * </p>
212: *
213: * @param viewSite the view site
214: * @throws PartInitException
215: */
216: public void init(IViewSite viewSite) throws PartInitException {
217: this .site = viewSite;
218: init();
219: }
220:
221: /**
222: * Initialize this style configurator.
223: * <p>
224: * You must call super.init();
225: * </p>
226: * @throws PartInitException
227: */
228: protected void init() throws PartInitException {
229: // subclass can override
230: }
231:
232: /**
233: * Determines if the configurator can be used to configure the style
234: * for a specified layer.
235: *
236: * @param aLayer The layer to be styled.
237: * @return true if the configurator can work with the layer, otherwise false.
238: */
239: public abstract boolean canStyle(Layer aLayer);
240:
241: /**
242: * Gets the current layer to which the current style being configured is
243: * to be applied to.
244: * <p>
245: * The layer can be <code>null</code> while the view is being initialized or created.
246: * This value must be non-<code>null</code> when the IStyleConfigurator.getControl()
247: * is visiable.
248: * </p>
249: * @return Layer being edited at the moment
250: */
251: public final Layer getLayer() {
252: return layer;
253: }
254:
255: /**
256: * Returns the style blackboard that the configurator is populating with
257: * style information.
258: * <p>
259: * <p>
260: * The blackboard can be <code>null</code> while the view is being initialized or created.
261: * This value must be non-<code>null</code> when the IStyleConfigurator.getControl()
262: * is visiable.
263: * </p>
264: * @return A style blackboard.
265: */
266: public final IBlackboard getStyleBlackboard() {
267: //return layer.style();
268: if (layer == null) {
269: return null;
270: }
271: return layer.getStyleBlackboard();
272: }
273:
274: /**
275: * Sets the layer and style blackboard that the configurator
276: * can populate with style.
277: * information. Upon this method, ui state should be reinitialized against
278: * the new layer and blackboard.
279: * <p>
280: * When changing layers:
281: * <ul>
282: * <li>setLayer( newLayer ) is called
283: * <li>setBlackboard( newBlackboard )
284: * <li>refresh()
285: * </p>
286: *
287: * @param layer1 The layer being styled.
288: */
289: public void focus(Layer layer1) {
290: this .layer = layer1;
291: //this.styleBlackboard = styleBlackboard;
292: refresh();
293: }
294:
295: /**
296: * Called when new layer and blackbard values are available.
297: * <p>
298: * This provides update information as a callback (rather than an
299: * event listener).
300: * </p>
301: * This should only be called after create part control has had a chance to
302: * be called.
303: */
304: protected abstract void refresh();
305:
306: /**
307: * Creates the control that is to be used to configure the style.
308: * <p>
309: * This method uses a template pattern to get the subclass to create
310: * the control. This method will not be called until after init and
311: * setViewPart. The parent container (composite) passed in is for the
312: * explicit use of the configurator, this method must set a layout for
313: * the container.
314: * </p>
315: * <p>
316: * You can set the layout to the parent to be whatever you want.
317: * </p>
318: * @param parent
319: */
320: public abstract void createControl(Composite parent);
321:
322: /**
323: * Cleans up any resources (like icons) held by this StyleConfigurator.
324: * <p>
325: * You should not assume that create, or even init has been called.
326: * You must call super.dispose();
327: * </p>
328: */
329: public void dispose() {
330: // subclass should override
331: }
332:
333: }
|