KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jimm > datavision > gui > SectionWidget


1 package jimm.datavision.gui;
2 import jimm.datavision.*;
3 import jimm.datavision.field.Field;
4 import jimm.datavision.gui.cmd.Command;
5 import jimm.datavision.gui.cmd.SectionResizeCommand;
6 import jimm.datavision.gui.cmd.SectionPageBreakCommand;
7 import java.util.*;
8 import java.awt.*;
9 import java.awt.event.*;
10 import javax.swing.*;
11
12 /**
13  * A section widget is the visual representation of a report section.
14  *
15  * @author Jim Menard, <a HREF="mailto:jimm@io.com">jimm@io.com</a>
16  */

17 public class SectionWidget extends JPanel implements ActionListener {
18
19 public static final int LHS_WIDTH = 125;
20
21 protected static final Font DEFAULT_POPUP_FONT =
22     new Font("Serif", Font.PLAIN, 10);
23
24 static final Color NORMAL_COLOR = Color.white;
25 static final Color SUPPRESSED_COLOR = Color.lightGray;
26
27 protected String JavaDoc name;
28 protected String JavaDoc popupName;
29 protected Designer designer;
30 protected Section section;
31 protected SectionNameLabel label;
32 protected SectionFieldPanel fieldPanel;
33 protected JPopupMenu popup;
34 protected JMenuItem nameItem, editSuppress;
35 protected JCheckBoxMenuItem togglePageBreak;
36 protected JMenuItem deleteGroup, addGroup, deleteSection, insertSection;
37
38 /**
39  * An inner class that handles display of the popup menu.
40  */

41 class PopupListener extends MouseAdapter {
42 public void mousePressed(MouseEvent e) { maybeShowPopup(e); }
43 public void mouseReleased(MouseEvent e) { maybeShowPopup(e); }
44 private void maybeShowPopup(MouseEvent e) {
45     if (e.isPopupTrigger())
46     showPopup(e);
47 }
48 }
49
50 /**
51  * Constructor.
52  *
53  * @param win parent design window
54  * @param sect the report section
55  * @param name a name such as "Report Header (a)"
56  */

57 public SectionWidget(Designer win, Section sect, String JavaDoc name) {
58     super();
59
60     designer = win;
61     section = sect;
62     this.name = name;
63     this.popupName = "";
64
65     setLayout(new SectionLayout());
66     setPreferredSize(new Dimension(getTotalWidth(), getHeight()));
67
68     buildPopupMenu();
69     addMouseListener(new PopupListener());
70
71     // LHS name of section
72
buildDisplayName();
73
74     // Fields
75
fieldPanel = new SectionFieldPanel(this);
76     fieldPanel.setLayout(null);
77     add(fieldPanel);
78     for (Iterator iter = section.fields(); iter.hasNext(); ) {
79     Field f = (Field)iter.next();
80     FieldWidget fw = f.makeWidget(this);
81     fieldPanel.add(fw.getComponent(), 0); // Add to top of visual stack.
82
}
83
84     // Let field panel set background color of itself and fields based
85
// on "always hide" suppression.
86
fieldPanel.setHidden(section.isHidden());
87
88     // If design window has initiated the drop of a new text field, create
89
// one. Else deselect all fields.
90
fieldPanel.addMouseListener(new PopupListener() {
91     public void mouseClicked(MouseEvent e) {
92         deselectAll();
93         if (designer.isPlacingNewTextField())
94         createNewTextField(e); // Calls acceptNewTextField()
95
}
96     });
97
98     // Resizer bar
99
add(new SectionResizer(this, designer.sectionContainer));
100 }
101
102 /**
103  * Builds the popup menu.
104  */

105 protected void buildPopupMenu() {
106     popup = new JPopupMenu(popupName);
107
108     nameItem =
109     MenuUtils.addToMenu(this, popup, "SectionWidget.popup_dummy_title",
110                 DEFAULT_POPUP_FONT);
111     popup.addSeparator();
112     editSuppress =
113     MenuUtils.addToMenu(this, popup, "SectionWidget.popup_suppress",
114                 DEFAULT_POPUP_FONT);
115     togglePageBreak =
116     MenuUtils.addCheckboxToMenu(this, popup,
117                     "SectionWidget.popup_page_break",
118                     DEFAULT_POPUP_FONT);
119     popup.addSeparator();
120     MenuUtils.addToMenu(this, popup, "SectionWidget.popup_shrink",
121             DEFAULT_POPUP_FONT);
122     popup.addSeparator();
123     deleteGroup =
124     MenuUtils.addToMenu(this, popup, "SectionWidget.popup_delete_group",
125                 DEFAULT_POPUP_FONT);
126     addGroup =
127     MenuUtils.addToMenu(this, popup, "SectionWidget.popup_add_group",
128                 DEFAULT_POPUP_FONT);
129     popup.addSeparator();
130     deleteSection =
131     MenuUtils.addToMenu(this, popup, "SectionWidget.popup_delete_section",
132                 DEFAULT_POPUP_FONT);
133     insertSection =
134     MenuUtils.addToMenu(this, popup, "SectionWidget.popup_insert_section",
135                 DEFAULT_POPUP_FONT);
136 }
137
138 /**
139  * Performs some action based on the action command string (the menu
140  * item text).
141  */

142 public void actionPerformed(ActionEvent e) {
143     String JavaDoc command = e.getActionCommand();
144     if (command == null) return;
145     if ("suppress".equals(command))
146     editSuppression();
147     else if ("page_break".equals(command))
148     togglePageBreak();
149     else if ("delete_group".equals(command))
150     designer.deleteGroupContaining(section);
151     else if ("add_group".equals(command))
152     designer.openNewGroupWin();
153     else if ("delete_section".equals(command))
154     designer.deleteSection(section);
155     else if ("insert_section_below".equals(command))
156     designer.insertSectionBelow(section);
157     else if ("shrink_to_fit".equals(command))
158     shrinkToFit();
159 }
160
161 /**
162  * Modifies menu items based on the state of the section.
163  */

164 protected void enablePopupMenuItems() {
165     nameItem.setText(popupName);
166     togglePageBreak.setSelected(section.hasPageBreak());
167     deleteSection.setEnabled(!section.getReport().isOneOfAKind(section));
168     deleteGroup.setEnabled(section.getReport().isInsideGroup(section));
169 }
170
171 /**
172  * Constructs the section name widget that is displayed to the left of
173  * the section.
174  */

175 protected void buildDisplayName() {
176     label = new SectionNameLabel(name, this);
177     add(label);
178 }
179
180 /**
181  * Set the section display name.
182  *
183  * @param name the new name
184  */

185 public void setDisplayName(String JavaDoc name) {
186     this.name = name;
187     label.setText(name);
188 }
189
190 /**
191  * Set the popup menu name, also displayed as first, disabled menu item.
192  *
193  * @param popupName the new name
194  */

195 public void setPopupName(String JavaDoc popupName) {
196     this.popupName = popupName;
197     nameItem.setText(popupName);
198 }
199
200 /**
201  * Returns the report we are representing.
202  *
203  * @return a report
204  */

205 public Report getReport() { return section.getReport(); }
206
207 /**
208  * Returns the section we are representing.
209  *
210  * @return a report section
211  */

212 public Section getSection() { return section; }
213
214 /**
215  * Returns the {@link SectionArea} of the {@link Section} (report header, page
216  * footer, etc.)
217  *
218  * @return the section's <code>SectionArea</code>
219  */

220 public SectionArea getSectionArea() { return section.getArea(); }
221
222 /**
223  * Returns the design window containing this section widget
224  *
225  * @return a design window
226  */

227 public Designer getDesigner() { return designer; }
228
229 /**
230  * Returns the width of the report paper (the white part upon which fields
231  * are placed).
232  *
233  * @return the paper width
234  */

235 public int getPaperWidth() {
236     return (int)section.getWidth();
237 }
238
239 /**
240  * Returns the width of the section, including the left-hand side name.
241  *
242  * @return the total width
243  */

244 public int getTotalWidth() {
245     return LHS_WIDTH + getPaperWidth();
246 }
247
248 /**
249  * Returns the height of the section, including the resizer bar.
250  *
251  * @return the total height
252  */

253 public int getHeight() {
254     return (int)section.getMinHeight() + SectionResizer.HEIGHT;
255 }
256
257 /**
258  * Returns the height of the report section.
259  *
260  * @return report section height
261  */

262 public int getSectionHeight() { return (int)section.getMinHeight(); }
263
264 /**
265  * Returns the minimum height the section needs to fit all of its fields.
266  *
267  * @return minimum height
268  */

269 public int getMinSectionHeight() {
270     int minY = 0;
271     Component[] fieldWidgets = fieldPanel.getComponents();
272     for (int i = 0; i < fieldWidgets.length; ++i) {
273     int y = fieldWidgets[i].getBounds().y
274         + fieldWidgets[i].getBounds().height;
275     if (y > minY)
276         minY = y;
277     }
278     return minY;
279 }
280
281 /**
282  * Resizes this widget. Called by the design window whenever the user
283  * selects a new paper size.
284  */

285 void paperSizeChanged() {
286     setPreferredSize(new Dimension(getTotalWidth(), getHeight()));
287     invalidate();
288 }
289
290 /**
291  * Toggles the suppressed flag of the section.
292  */

293 void editSuppression() {
294     new SuppressionProcWin(designer, this);
295 }
296
297 /**
298  * Toggles the page break flag of the section.
299  */

300 void togglePageBreak() {
301     performCommand(new SectionPageBreakCommand(section));
302 }
303
304 /**
305  * Shrinks this section widget to the minimum height required. This method
306  * is only called from the popup menu. It should not be called as part
307  * of a larger operation because it creates a command that allows undo/redo.
308  */

309 public void shrinkToFit() {
310     SectionResizeCommand cmd = new SectionResizeCommand(this);
311     growBy(getMinSectionHeight() - getSectionHeight());
312     performCommand(cmd);
313 }
314
315 /**
316  * Grows this section widget to the minimum height required. This method,
317  * unlike <code>shrinkToFit</code>, is always called as part of some other
318  * operation.
319  */

320 public void growToFit() {
321     int dy = getMinSectionHeight() - getSectionHeight();
322
323     if (dy > 0)
324     growBy(dy);
325 }
326
327 /**
328  * Resizes the section. Called by resizer bar and by commands that
329  * grow sections as a side effect.
330  *
331  * @param dy delta y
332  */

333 public void growBy(int dy) {
334     if (dy == 0) return;
335
336     // Make sure section fits all fields.
337
int origHeight = (int)section.getMinHeight();
338     int newHeight = origHeight + dy;
339     int minHeight = getMinSectionHeight();
340     if (newHeight < minHeight) {
341     newHeight = minHeight;
342     if (newHeight == origHeight)
343         return;
344     }
345
346     section.setMinHeight(newHeight); // Hight not including resizer
347
setPreferredSize(new Dimension(getTotalWidth(), getHeight())); // Incl. resizer
348
revalidate();
349 }
350
351 /**
352  * Grows or shrinks the section widget and executes a command that allows
353  * this action to be undone/redone. Calls {@link #growBy} to grow
354  * or shrink, then lets our window execute the command that remembers
355  * the size change for later undo/redo.
356  * <p>
357  * The command does not change our height. It remembers the old and new
358  * heights for later undo/redo.
359  *
360  * @param dy delta height
361  * @param cmd a section resize command
362  * @see #performCommand
363  */

364 public void resizeBy(int dy, SectionResizeCommand cmd) {
365     growBy(dy);
366     performCommand(cmd);
367 }
368
369 /**
370  * Passes a command up to the design window for execution.
371  *
372  * @param cmd a command
373  * @see Designer#performCommand
374  */

375 public void performCommand(Command cmd) {
376     designer.performCommand(cmd);
377 }
378
379 /**
380  * Passes responsiblity up to the design window.
381  * @see Designer#setIgnoreKeys
382  */

383 public void setIgnoreKeys(boolean ignoreKeys) {
384     designer.setIgnoreKeys(ignoreKeys);
385 }
386
387 /**
388  * Passes this request up to the design window.
389  *
390  * @param x where to place the title
391  * @param width how wide it should be
392  * @param title the string to display
393  * @return the newly-created widget
394  * @see Designer#addTitleField
395  */

396 public FieldWidget addTitleField(int x, int width, String JavaDoc title) {
397     return designer.addTitleField(x, width, title);
398 }
399
400 /**
401  * Passes on to the design window the request to pick up all selected fields
402  * for dragging (not just the specified field). Called from {@link
403  * FieldWidget#mousePressed}.
404  *
405  * @param mouseScreenPos the location of the mouse in screen coordinates
406  * @see Designer#pickUp
407  */

408 void pickUp(java.awt.Point JavaDoc mouseScreenPos) {
409     designer.pickUp(mouseScreenPos);
410 }
411
412 /**
413  * Passes on to the design window the request to put down all fields being
414  * dragged (not just the specified field). Called from {@link
415  * FieldWidget#mouseReleased}.
416  *
417  * @param f the field in which the mouse has been clicked
418  * @param origScreenPos the original location of the field in screen
419  * coordinates
420  * @param mouseScreenPos the location of the mouse in screen coordinates
421  * @see Designer#putDown
422  */

423 void putDown(FieldWidget f, java.awt.Point JavaDoc origScreenPos,
424          java.awt.Point JavaDoc mouseScreenPos)
425 {
426     designer.putDown(f, origScreenPos, mouseScreenPos);
427 }
428
429 /**
430  * Passes on to the design window the request to start stretching all selected
431  * fields (not just the specified field). Called from {@link
432  * FieldWidget#mousePressed}.
433  *
434  * @param mouseScreenPos the location of the mouse in screen coordinates
435  * @see Designer#startStretching
436  */

437 void startStretching(java.awt.Point JavaDoc mouseScreenPos) {
438     designer.startStretching(mouseScreenPos);
439 }
440
441 /**
442  * Passes on to the design window the request to stop stretching all fields
443  * being stretched (not just the specified field). Called from {@link
444  * FieldWidget#mouseReleased}.
445  *
446  * @param f the field in which the mouse has been clicked
447  * @param origBounds the field's original bounds
448  * @see Designer#putDown
449  */

450 void stopStretching(FieldWidget f, jimm.datavision.field.Rectangle origBounds)
451 {
452     designer.stopStretching(f, origBounds);
453 }
454
455 /**
456  * Tells the window to drag (move, resize) all selected fields. Called
457  * from one field widget when it's being manipulated with the mouse.
458  *
459  * @param action a <code>FieldWidget.ACTION_*</code> constant
460  * @param mouseScreenPos the location of the mouse in screen coordinates
461  * @see FieldWidget#mouseDragged
462  * @see Designer#dragSelectedWidgets
463  */

464 void dragSelectedWidgets(int action, java.awt.Point JavaDoc mouseScreenPos) {
465     designer.dragSelectedWidgets(action, mouseScreenPos);
466 }
467
468 /**
469  * Selects or deselcts a field widget, possibly deselecting all others
470  * everywhere. Called from field widget itself, this passes the request
471  * on to the design window.
472  *
473  * @param fieldWidget a field widget
474  * @param makeSelected if <code>true</code>, select this field; else
475  * deselect it
476  * @param deselectOthers if <code>true</code>, all other fields in all
477  * sections are deselected first
478  * @see Designer#select
479  */

480 void select(FieldWidget fieldWidget, boolean makeSelected,
481         boolean deselectOthers)
482 {
483     designer.select(fieldWidget, makeSelected, deselectOthers);
484 }
485
486 /**
487  * Deselects all fields in all sections. Tells the design window to do
488  * so.
489  *
490  * @see Designer#deselectAll
491  */

492 void deselectAll() {
493     designer.deselectAll();
494 }
495
496 /**
497  * Adds field widget to panel. Does not affect models. Field retains its
498  * selection state.
499  *
500  * @param fw field widget to add
501  */

502 public void addField(FieldWidget fw) {
503     fieldPanel.add(fw.getComponent(), 0); // Add to top of visual stack.
504
fw.sectionWidget = this;
505     fw.getComponent().setBackground(section.isHidden()
506                     ? SUPPRESSED_COLOR : NORMAL_COLOR);
507     growToFit();
508 }
509
510 /**
511  * Removes field widget from panel, but do not change field model's relation
512  * with section model. Field retains its selection state.
513  * <p>
514  * To delete a field widget completely, see {@link
515  * Designer#deleteSelectedFields}.
516  *
517  * @param fw field widget to remove
518  * @see #addField
519  */

520 public void removeField(FieldWidget fw) {
521     fieldPanel.remove(fw.getComponent());
522 }
523
524 public SectionFieldPanel getFieldPanel() { return fieldPanel; }
525
526 /**
527  * Asks the design window to snap the rectangle to it's grid.
528  *
529  * @param r a rectangle
530  */

531 void snapToGrid(jimm.datavision.field.Rectangle r) {
532     designer.snapToGrid(r);
533 }
534
535 /**
536  * Sets the visibility of all selected fields plus the one passed in.
537  * Passes the buck to the design window.
538  *
539  * @see FieldWidget#toggleVisibility
540  * @see Designer#setFieldVisibility
541  */

542 void setFieldVisibility(boolean newVisiblity, FieldWidget fw) {
543     designer.setFieldVisibility(newVisiblity, fw);
544 }
545
546 /**
547  * Asks design window to create and accepts a new text field.
548  *
549  * @see Designer#createNewTextField
550  */

551 void createNewTextField(MouseEvent e) {
552     designer.createNewTextField(this, e);
553 }
554
555 /**
556  * Displays popup menu, after enabling and disabling menu items.
557  *
558  * @param e mouse event that caused popup to do its thing
559  */

560 void showPopup(MouseEvent e) {
561     enablePopupMenuItems();
562     popup.show(e.getComponent(), e.getX(), e.getY());
563 }
564
565 }
566
Popular Tags