1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.vectomatic.svg.edit.client.gxt.panels;
19
20 import java.util.List;
21
22 import org.vectomatic.dom.svg.OMSVGPaint;
23 import org.vectomatic.dom.svg.utils.SVGConstants;
24 import org.vectomatic.svg.edit.client.AppBundle;
25 import org.vectomatic.svg.edit.client.AppConstants;
26 import org.vectomatic.svg.edit.client.SvgrealApp;
27 import org.vectomatic.svg.edit.client.command.CommandFactorySelector;
28 import org.vectomatic.svg.edit.client.command.CommandStore;
29 import org.vectomatic.svg.edit.client.command.ICommand;
30 import org.vectomatic.svg.edit.client.command.ICommandFactory;
31 import org.vectomatic.svg.edit.client.command.IFactoryInstantiator;
32 import org.vectomatic.svg.edit.client.engine.Grid;
33 import org.vectomatic.svg.edit.client.engine.SVGModel;
34 import org.vectomatic.svg.edit.client.event.ActivateWindowEvent;
35 import org.vectomatic.svg.edit.client.event.ActivateWindowHandler;
36 import org.vectomatic.svg.edit.client.event.CommandFactorySelectorChangeEvent;
37 import org.vectomatic.svg.edit.client.event.CommandFactorySelectorChangeHandler;
38 import org.vectomatic.svg.edit.client.event.DeactivateWindowEvent;
39 import org.vectomatic.svg.edit.client.event.DeactivateWindowHandler;
40 import org.vectomatic.svg.edit.client.event.SelectionChangedProcessor;
41 import org.vectomatic.svg.edit.client.event.SelectionChangedProxy;
42 import org.vectomatic.svg.edit.client.gxt.widget.BlurComboBox;
43 import org.vectomatic.svg.edit.client.gxt.widget.PaintCell;
44 import org.vectomatic.svg.edit.client.gxt.widget.RedoCommandMenuItem;
45 import org.vectomatic.svg.edit.client.gxt.widget.UndoCommandMenuItem;
46 import org.vectomatic.svg.edit.client.model.svg.CssContextModel;
47
48 import com.extjs.gxt.ui.client.data.BeanModel;
49 import com.extjs.gxt.ui.client.data.ChangeEvent;
50 import com.extjs.gxt.ui.client.data.ChangeListener;
51 import com.extjs.gxt.ui.client.event.ButtonEvent;
52 import com.extjs.gxt.ui.client.event.MenuEvent;
53 import com.extjs.gxt.ui.client.event.SelectionChangedEvent;
54 import com.extjs.gxt.ui.client.event.SelectionListener;
55 import com.extjs.gxt.ui.client.store.ListStore;
56 import com.extjs.gxt.ui.client.store.StoreEvent;
57 import com.extjs.gxt.ui.client.store.StoreListener;
58 import com.extjs.gxt.ui.client.util.Format;
59 import com.extjs.gxt.ui.client.widget.Label;
60 import com.extjs.gxt.ui.client.widget.Status;
61 import com.extjs.gxt.ui.client.widget.WidgetComponent;
62 import com.extjs.gxt.ui.client.widget.button.Button;
63 import com.extjs.gxt.ui.client.widget.button.SplitButton;
64 import com.extjs.gxt.ui.client.widget.form.ComboBox.TriggerAction;
65 import com.extjs.gxt.ui.client.widget.menu.CheckMenuItem;
66 import com.extjs.gxt.ui.client.widget.menu.Menu;
67 import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem;
68 import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
69 import com.google.gwt.core.client.GWT;
70 import com.google.gwt.dom.client.Style.Position;
71 import com.google.gwt.dom.client.Style.Unit;
72 import com.google.gwt.event.dom.client.ClickEvent;
73 import com.google.gwt.event.dom.client.ClickHandler;
74 import com.google.gwt.user.client.ui.AbstractImagePrototype;
75
76
77
78
79
80 public class CommandFactoryToolBar extends ToolBar implements CommandFactorySelectorChangeHandler, ActivateWindowHandler, DeactivateWindowHandler, SelectionChangedProcessor<IFactoryInstantiator<?>> {
81
82
83
84 private CommandFactorySelector factorySelector;
85
86
87
88 private BlurComboBox<IFactoryInstantiator<?>> factoryCombo;
89
90
91
92 private Button cancelButton;
93
94
95
96 private SplitButton undoButton;
97
98
99
100 private SplitButton redoButton;
101
102
103
104 private Menu undoMenu;
105
106
107
108 private Menu redoMenu;
109
110
111
112 private Status status;
113
114
115
116 private CommandStore currentCommandStore;
117
118
119
120 private boolean silent;
121
122
123
124 private PaintCell strokeCell;
125
126
127
128 private PaintCell fillCell;
129
130
131
132 private SplitButton gridButton;
133 private CheckMenuItem showGridItem;
134 private CheckMenuItem showGuidesItem;
135 private CheckMenuItem snapToGridItem;
136
137
138
139 private Label xLabel;
140
141
142
143 private Label yLabel;
144
145 private StoreListener<BeanModel> commandStoreListener = new StoreListener<BeanModel>() {
146 public void storeAdd(StoreEvent<BeanModel> se) {
147 updateUndoRedo();
148 }
149
150 public void storeFilter(StoreEvent<BeanModel> se) {
151 updateUndoRedo();
152 }
153 };
154
155 public CommandFactoryToolBar(ListStore<IFactoryInstantiator<?>> factoryStore, CommandFactorySelector factoryStack) {
156 setSpacing(2);
157 this.factorySelector = factoryStack;
158 factoryStack.addCommandFactoryChangeHandler(this);
159 AppConstants constants = AppConstants.INSTANCE;
160 factoryCombo = new BlurComboBox<IFactoryInstantiator<?>>();
161 factoryCombo.setEmptyText(constants.selectCommand());
162 factoryCombo.setStore(factoryStore);
163 factoryCombo.setDisplayField(IFactoryInstantiator.NAME);
164 factoryCombo.setItemSelector("div.command-factory");
165 factoryCombo.setTemplate(getTemplate());
166 factoryCombo.setWidth(200);
167 factoryCombo.setMinListWidth(500);
168 factoryCombo.setPageSize(5);
169 factoryCombo.setTypeAhead(true);
170 factoryCombo.setTriggerAction(TriggerAction.ALL);
171 factoryCombo.addSelectionChangedListener(new SelectionChangedProxy<IFactoryInstantiator<?>>(this));
172 cancelButton = new Button(constants.cancelButton());
173 cancelButton.addSelectionListener(new SelectionListener<ButtonEvent>() {
174 @Override
175 public void componentSelected(ButtonEvent ce) {
176 cancelCommandFactory();
177 }
178 });
179 cancelButton.setEnabled(false);
180 undoButton = new SplitButton();
181 undoButton.setIcon(AbstractImagePrototype.create(AppBundle.INSTANCE.undo()));
182 undoButton.addSelectionListener(new SelectionListener<ButtonEvent>() {
183 @Override
184 public void componentSelected(ButtonEvent ce) {
185 undoCommand();
186 }
187 });
188 undoMenu = new Menu();
189 undoButton.setMenu(undoMenu);
190 redoButton = new SplitButton();
191 redoButton.setIcon(AbstractImagePrototype.create(AppBundle.INSTANCE.redo()));
192 redoButton.addSelectionListener(new SelectionListener<ButtonEvent>() {
193 @Override
194 public void componentSelected(ButtonEvent ce) {
195 redoCommand();
196 }
197 });
198 redoMenu = new Menu();
199 redoButton.setMenu(redoMenu);
200 status = new Status();
201 Label strokeLabel = new Label(constants.stroke() + ":");
202 ClickHandler clickHandler = new ClickHandler() {
203 @Override
204 public void onClick(ClickEvent event) {
205 SVGModel model = SvgrealApp.getApp().getActiveModel();
206 if (model != null) {
207 model.getSelectionModel().deselectAll();
208 }
209 SvgrealApp.getApp().inspector();
210 }
211 };
212 strokeCell = new PaintCell();
213 strokeCell.getStyle().setWidth(15, Unit.PX);
214 strokeCell.getStyle().setHeight(15, Unit.PX);
215 strokeCell.addClickHandler(clickHandler);
216 strokeCell.getElement().getStyle().setPosition(Position.RELATIVE);
217 strokeCell.getElement().getStyle().setTop(2, Unit.PX);
218 Label fillLabel = new Label(constants.fill() + ":");
219 fillCell = new PaintCell();
220 fillCell.getStyle().setWidth(15, Unit.PX);
221 fillCell.getStyle().setHeight(15, Unit.PX);
222 fillCell.addClickHandler(clickHandler);
223 fillCell.getElement().getStyle().setPosition(Position.RELATIVE);
224 fillCell.getElement().getStyle().setTop(2, Unit.PX);
225 updatePaint();
226 SvgrealApp.getApp().getCssContext().addChangeListener(new ChangeListener() {
227 @Override
228 public void modelChanged(ChangeEvent event) {
229 updatePaint();
230 }
231 });
232 showGridItem = new CheckMenuItem(AppConstants.INSTANCE.showGrid());
233 showGridItem.addSelectionListener(new SelectionListener<MenuEvent>() {
234 @Override
235 public void componentSelected(MenuEvent ce) {
236 Grid grid = SvgrealApp.getApp().getActiveModel().getGrid();
237 grid.setShowsGrid(((CheckMenuItem)ce.getItem()).isChecked());
238 }
239 });
240 showGuidesItem = new CheckMenuItem(AppConstants.INSTANCE.showGuides());
241 showGuidesItem.addSelectionListener(new SelectionListener<MenuEvent>() {
242 @Override
243 public void componentSelected(MenuEvent ce) {
244 Grid grid = SvgrealApp.getApp().getActiveModel().getGrid();
245 grid.setShowsGuides(((CheckMenuItem)ce.getItem()).isChecked());
246 }
247 });
248 snapToGridItem = new CheckMenuItem(AppConstants.INSTANCE.snapToGrid());
249 snapToGridItem.addSelectionListener(new SelectionListener<MenuEvent>() {
250 @Override
251 public void componentSelected(MenuEvent ce) {
252 Grid grid = SvgrealApp.getApp().getActiveModel().getGrid();
253 grid.setSnapsToGrid(((CheckMenuItem)ce.getItem()).isChecked());
254 }
255 });
256 Menu gridMenu = new Menu();
257 gridMenu.add(showGridItem);
258 gridMenu.add(showGuidesItem);
259 gridMenu.add(snapToGridItem);
260 gridButton = new SplitButton(AppConstants.INSTANCE.grid());
261 gridButton.setIcon(AbstractImagePrototype.create(AppBundle.INSTANCE.grid()));
262 gridButton.setMenu(gridMenu);
263
264 add(strokeLabel);
265 add(new WidgetComponent(strokeCell));
266 add(fillLabel);
267 add(new WidgetComponent(fillCell));
268 add(new SeparatorToolItem());
269 add(gridButton);
270 add(new SeparatorToolItem());
271 add(factoryCombo);
272 add(new SeparatorToolItem());
273 add(undoButton);
274 add(redoButton);
275 add(new SeparatorToolItem());
276 add(cancelButton);
277 add(new SeparatorToolItem());
278 add(status);
279 SvgrealApp.getApp().addActivateWindowHandler(this);
280 SvgrealApp.getApp().addDeactivateWindowHandler(this);
281 }
282
283 private void updatePaint() {
284 CssContextModel context = SvgrealApp.getApp().getCssContext();
285 strokeCell.setPaint(context.<OMSVGPaint>get(SVGConstants.CSS_STROKE_PROPERTY));
286 fillCell.setPaint(context.<OMSVGPaint>get(SVGConstants.CSS_FILL_PROPERTY));
287 }
288
289 @Override
290 public boolean processSelectionChanged(SelectionChangedEvent<IFactoryInstantiator<?>> se) {
291 List<IFactoryInstantiator<?>> selection = se.getSelection();
292 GWT.log("CommandFactoryToolBar.selectionChanged(" + selection + ")");
293 if (!silent) {
294 if (selection.size() == 1) {
295
296 ICommandFactory factory = factorySelector.getActiveFactory();
297 if (factory != null) {
298 factory.stop();
299 }
300 selection.get(0).create().start(CommandFactoryToolBar.this);
301 }
302 }
303 factoryCombo.triggerBlur();
304 return true;
305 }
306
307 private native String getTemplate()
308
309
310
311
312
313
314 ;
315
316 @Override
317 public void onChange(CommandFactorySelectorChangeEvent event) {
318 silent = true;
319 ICommandFactory factory = event.getCommandFactory();
320 GWT.log("CommandFactoryToolBar.onChange(" + factory + ")");
321 if (factory != null) {
322 factoryCombo.disableEvents(true);
323 factoryCombo.setValue(factory.getInstantiator());
324 factoryCombo.disableEvents(false);
325 status.setText(factory.getStatus());
326 } else {
327 factoryCombo.setValue(null);
328 factoryCombo.clearSelections();
329 status.setText("");
330 }
331 cancelButton.setEnabled(factorySelector.getActiveFactory() != null);
332 silent = false;
333 }
334
335 private void updateUndoRedo() {
336 GWT.log("CommandFactoryToolBar.updateUndoRedo()");
337 undoButton.setEnabled(currentCommandStore != null && currentCommandStore.canUndo());
338 redoButton.setEnabled(currentCommandStore != null && currentCommandStore.canRedo());
339 if (currentCommandStore != null) {
340 String undoTooltip = null;
341 if (currentCommandStore.canUndo()) {
342 undoMenu.removeAll();
343 for (BeanModel command : currentCommandStore.getUndoCommands()) {
344 undoMenu.add(new UndoCommandMenuItem(currentCommandStore, command));
345 }
346 undoButton.setMenu(undoMenu);
347 undoTooltip = Format.capitalize(
348 AppConstants.INSTANCE.undoButton()
349 + " "
350 + ((ICommand)currentCommandStore.getUndoCommand().getBean()).getDescription());
351 }
352 undoButton.setToolTip(undoTooltip);
353 String redoTooltip = null;
354 if (currentCommandStore.canRedo()) {
355 redoMenu.removeAll();
356 for (BeanModel command : currentCommandStore.getRedoCommands()) {
357 redoMenu.add(new RedoCommandMenuItem(currentCommandStore, command));
358 }
359 redoButton.setMenu(redoMenu);
360 redoTooltip = Format.capitalize(
361 AppConstants.INSTANCE.redoButton()
362 + " "
363 + ((ICommand)currentCommandStore.getRedoCommand().getBean()).getDescription());
364 }
365 redoButton.setToolTip(redoTooltip);
366 }
367 }
368
369 public void updateStatus() {
370 ICommandFactory currentFactory = factorySelector.getActiveFactory();
371 status.setText(currentFactory != null ? currentFactory.getStatus() : "");
372 }
373
374 private void cancelCommandFactory() {
375 GWT.log("CommandFactoryToolBar.cancelCommandFactory()");
376 factorySelector.getActiveFactory().stop();
377 }
378
379 private void undoCommand() {
380 GWT.log("CommandFactoryToolBar.undoCommand()");
381 currentCommandStore.undo();
382 }
383
384 private void redoCommand() {
385 GWT.log("CommandFactoryToolBar.redoCommand()");
386 currentCommandStore.redo();
387 }
388
389 @Override
390 public void onDeactivate(DeactivateWindowEvent event) {
391 GWT.log("CommandFactoryToolBar.onDeactivate");
392 event.getWindow().getSvgModel().getCommandStore().removeStoreListener(commandStoreListener);
393
394
395 currentCommandStore = null;
396 updateUndoRedo();
397
398
399 gridButton.setEnabled(false);
400 }
401
402 @Override
403 public void onActivate(ActivateWindowEvent event) {
404 GWT.log("CommandFactoryToolBar.onActivate");
405 SVGModel model = event.getWindow().getSvgModel();
406
407
408 currentCommandStore = model.getCommandStore();
409 currentCommandStore.addStoreListener(commandStoreListener);
410 updateUndoRedo();
411
412
413 Grid grid = model.getGrid();
414 showGridItem.setChecked(grid.showsGrid(), true);
415 showGuidesItem.setChecked(grid.showsGuides(), true);
416 snapToGridItem.setChecked(grid.snapsToGrid(), true);
417 gridButton.setEnabled(true);
418 }
419 }