Package jimm.datavision.gui

Source Code of jimm.datavision.gui.SectionWidget

package jimm.datavision.gui;
import jimm.datavision.*;
import jimm.datavision.field.Field;
import jimm.datavision.gui.cmd.Command;
import jimm.datavision.gui.cmd.SectionResizeCommand;
import jimm.datavision.gui.cmd.SectionPageBreakCommand;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

/**
* A section widget is the visual representation of a report section.
*
* @author Jim Menard, <a href="mailto:jimm@io.com">jimm@io.com</a>
*/
public class SectionWidget extends JPanel implements ActionListener {

public static final int LHS_WIDTH = 125;

protected static final Font DEFAULT_POPUP_FONT =
    new Font("Serif", Font.PLAIN, 10);

static final Color NORMAL_COLOR = Color.white;
static final Color SUPPRESSED_COLOR = Color.lightGray;

protected String name;
protected String popupName;
protected Designer designer;
protected Section section;
protected SectionNameLabel label;
protected SectionFieldPanel fieldPanel;
protected JPopupMenu popup;
protected JMenuItem nameItem, editSuppress;
protected JCheckBoxMenuItem togglePageBreak;
protected JMenuItem deleteGroup, addGroup, deleteSection, insertSection;

/**
* An inner class that handles display of the popup menu.
*/
class PopupListener extends MouseAdapter {
public void mousePressed(MouseEvent e) { maybeShowPopup(e); }
public void mouseReleased(MouseEvent e) { maybeShowPopup(e); }
private void maybeShowPopup(MouseEvent e) {
    if (e.isPopupTrigger())
  showPopup(e);
}
}

/**
* Constructor.
*
* @param win parent design window
* @param sect the report section
* @param name a name such as "Report Header (a)"
*/
public SectionWidget(Designer win, Section sect, String name) {
    super();

    designer = win;
    section = sect;
    this.name = name;
    this.popupName = "";

    setLayout(new SectionLayout());
    setPreferredSize(new Dimension(getTotalWidth(), getHeight()));

    buildPopupMenu();
    addMouseListener(new PopupListener());

    // LHS name of section
    buildDisplayName();

    // Fields
    fieldPanel = new SectionFieldPanel(this);
    fieldPanel.setLayout(null);
    add(fieldPanel);
    for (Iterator iter = section.fields(); iter.hasNext(); ) {
  Field f = (Field)iter.next();
  FieldWidget fw = f.makeWidget(this);
  fieldPanel.add(fw.getComponent(), 0)// Add to top of visual stack.
    }

    // Let field panel set background color of itself and fields based
    // on "always hide" suppression.
    fieldPanel.setHidden(section.isHidden());

    // If design window has initiated the drop of a new text field, create
    // one. Else deselect all fields.
    fieldPanel.addMouseListener(new PopupListener() {
  public void mouseClicked(MouseEvent e) {
      deselectAll();
      if (designer.isPlacingNewTextField())
    createNewTextField(e); // Calls acceptNewTextField()
  }
  });

    // Resizer bar
    add(new SectionResizer(this, designer.sectionContainer));
}

/**
* Builds the popup menu.
*/
protected void buildPopupMenu() {
    popup = new JPopupMenu(popupName);

    nameItem =
  MenuUtils.addToMenu(this, popup, "SectionWidget.popup_dummy_title",
          DEFAULT_POPUP_FONT);
    popup.addSeparator();
    editSuppress =
  MenuUtils.addToMenu(this, popup, "SectionWidget.popup_suppress",
          DEFAULT_POPUP_FONT);
    togglePageBreak =
  MenuUtils.addCheckboxToMenu(this, popup,
            "SectionWidget.popup_page_break",
            DEFAULT_POPUP_FONT);
    popup.addSeparator();
    MenuUtils.addToMenu(this, popup, "SectionWidget.popup_shrink",
      DEFAULT_POPUP_FONT);
    popup.addSeparator();
    deleteGroup =
  MenuUtils.addToMenu(this, popup, "SectionWidget.popup_delete_group",
          DEFAULT_POPUP_FONT);
    addGroup =
  MenuUtils.addToMenu(this, popup, "SectionWidget.popup_add_group",
          DEFAULT_POPUP_FONT);
    popup.addSeparator();
    deleteSection =
  MenuUtils.addToMenu(this, popup, "SectionWidget.popup_delete_section",
          DEFAULT_POPUP_FONT);
    insertSection =
  MenuUtils.addToMenu(this, popup, "SectionWidget.popup_insert_section",
          DEFAULT_POPUP_FONT);
}

/**
* Performs some action based on the action command string (the menu
* item text).
*/
public void actionPerformed(ActionEvent e) {
    String command = e.getActionCommand();
    if (command == null) return;
    if ("suppress".equals(command))
  editSuppression();
    else if ("page_break".equals(command))
  togglePageBreak();
    else if ("delete_group".equals(command))
  designer.deleteGroupContaining(section);
    else if ("add_group".equals(command))
  designer.openNewGroupWin();
    else if ("delete_section".equals(command))
  designer.deleteSection(section);
    else if ("insert_section_below".equals(command))
  designer.insertSectionBelow(section);
    else if ("shrink_to_fit".equals(command))
  shrinkToFit();
}

/**
* Modifies menu items based on the state of the section.
*/
protected void enablePopupMenuItems() {
    nameItem.setText(popupName);
    togglePageBreak.setSelected(section.hasPageBreak());
    deleteSection.setEnabled(!section.getReport().isOneOfAKind(section));
    deleteGroup.setEnabled(section.getReport().isInsideGroup(section));
}

/**
* Constructs the section name widget that is displayed to the left of
* the section.
*/
protected void buildDisplayName() {
    label = new SectionNameLabel(name, this);
    add(label);
}

/**
* Set the section display name.
*
* @param name the new name
*/
public void setDisplayName(String name) {
    this.name = name;
    label.setText(name);
}

/**
* Set the popup menu name, also displayed as first, disabled menu item.
*
* @param popupName the new name
*/
public void setPopupName(String popupName) {
    this.popupName = popupName;
    nameItem.setText(popupName);
}

/**
* Returns the report we are representing.
*
* @return a report
*/
public Report getReport() { return section.getReport(); }

/**
* Returns the section we are representing.
*
* @return a report section
*/
public Section getSection() { return section; }

/**
* Returns the {@link SectionArea} of the {@link Section} (report header, page
* footer, etc.)
*
* @return the section's <code>SectionArea</code>
*/
public SectionArea getSectionArea() { return section.getArea(); }

/**
* Returns the design window containing this section widget
*
* @return a design window
*/
public Designer getDesigner() { return designer; }

/**
* Returns the width of the report paper (the white part upon which fields
* are placed).
*
* @return the paper width
*/
public int getPaperWidth() {
    return (int)section.getWidth();
}

/**
* Returns the width of the section, including the left-hand side name.
*
* @return the total width
*/
public int getTotalWidth() {
    return LHS_WIDTH + getPaperWidth();
}

/**
* Returns the height of the section, including the resizer bar.
*
* @return the total height
*/
public int getHeight() {
    return (int)section.getMinHeight() + SectionResizer.HEIGHT;
}

/**
* Returns the height of the report section.
*
* @return report section height
*/
public int getSectionHeight() { return (int)section.getMinHeight(); }

/**
* Returns the minimum height the section needs to fit all of its fields.
*
* @return minimum height
*/
public int getMinSectionHeight() {
    int minY = 0;
    Component[] fieldWidgets = fieldPanel.getComponents();
    for (int i = 0; i < fieldWidgets.length; ++i) {
  int y = fieldWidgets[i].getBounds().y
      + fieldWidgets[i].getBounds().height;
  if (y > minY)
      minY = y;
    }
    return minY;
}

/**
* Resizes this widget. Called by the design window whenever the user
* selects a new paper size.
*/
void paperSizeChanged() {
    setPreferredSize(new Dimension(getTotalWidth(), getHeight()));
    invalidate();
}

/**
* Toggles the suppressed flag of the section.
*/
void editSuppression() {
    new SuppressionProcWin(designer, this);
}

/**
* Toggles the page break flag of the section.
*/
void togglePageBreak() {
    performCommand(new SectionPageBreakCommand(section));
}

/**
* Shrinks this section widget to the minimum height required. This method
* is only called from the popup menu. It should not be called as part
* of a larger operation because it creates a command that allows undo/redo.
*/
public void shrinkToFit() {
    SectionResizeCommand cmd = new SectionResizeCommand(this);
    growBy(getMinSectionHeight() - getSectionHeight());
    performCommand(cmd);
}

/**
* Grows this section widget to the minimum height required. This method,
* unlike <code>shrinkToFit</code>, is always called as part of some other
* operation.
*/
public void growToFit() {
    int dy = getMinSectionHeight() - getSectionHeight();

    if (dy > 0)
  growBy(dy);
}

/**
* Resizes the section. Called by resizer bar and by commands that
* grow sections as a side effect.
*
* @param dy delta y
*/
public void growBy(int dy) {
    if (dy == 0) return;

    // Make sure section fits all fields.
    int origHeight = (int)section.getMinHeight();
    int newHeight = origHeight + dy;
    int minHeight = getMinSectionHeight();
    if (newHeight < minHeight) {
  newHeight = minHeight;
  if (newHeight == origHeight)
      return;
    }

    section.setMinHeight(newHeight); // Hight not including resizer
    setPreferredSize(new Dimension(getTotalWidth(), getHeight())); // Incl. resizer
    revalidate();
}

/**
* Grows or shrinks the section widget and executes a command that allows
* this action to be undone/redone. Calls {@link #growBy} to grow
* or shrink, then lets our window execute the command that remembers
* the size change for later undo/redo.
* <p>
* The command does not change our height. It remembers the old and new
* heights for later undo/redo.
*
* @param dy delta height
* @param cmd a section resize command
* @see #performCommand
*/
public void resizeBy(int dy, SectionResizeCommand cmd) {
    growBy(dy);
    performCommand(cmd);
}

/**
* Passes a command up to the design window for execution.
*
* @param cmd a command
* @see Designer#performCommand
*/
public void performCommand(Command cmd) {
    designer.performCommand(cmd);
}

/**
* Passes responsiblity up to the design window.
* @see Designer#setIgnoreKeys
*/
public void setIgnoreKeys(boolean ignoreKeys) {
    designer.setIgnoreKeys(ignoreKeys);
}

/**
* Passes this request up to the design window.
*
* @param x where to place the title
* @param width how wide it should be
* @param title the string to display
* @return the newly-created widget
* @see Designer#addTitleField
*/
public FieldWidget addTitleField(int x, int width, String title) {
    return designer.addTitleField(x, width, title);
}

/**
* Passes on to the design window the request to pick up all selected fields
* for dragging (not just the specified field). Called from {@link
* FieldWidget#mousePressed}.
*
* @param mouseScreenPos the location of the mouse in screen coordinates
* @see Designer#pickUp
*/
void pickUp(java.awt.Point mouseScreenPos) {
    designer.pickUp(mouseScreenPos);
}

/**
* Passes on to the design window the request to put down all fields being
* dragged (not just the specified field). Called from {@link
* FieldWidget#mouseReleased}.
*
* @param f the field in which the mouse has been clicked
* @param origScreenPos the original location of the field in screen
* coordinates
* @param mouseScreenPos the location of the mouse in screen coordinates
* @see Designer#putDown
*/
void putDown(FieldWidget f, java.awt.Point origScreenPos,
       java.awt.Point mouseScreenPos)
{
    designer.putDown(f, origScreenPos, mouseScreenPos);
}

/**
* Passes on to the design window the request to start stretching all selected
* fields (not just the specified field). Called from {@link
* FieldWidget#mousePressed}.
*
* @param mouseScreenPos the location of the mouse in screen coordinates
* @see Designer#startStretching
*/
void startStretching(java.awt.Point mouseScreenPos) {
    designer.startStretching(mouseScreenPos);
}

/**
* Passes on to the design window the request to stop stretching all fields
* being stretched (not just the specified field). Called from {@link
* FieldWidget#mouseReleased}.
*
* @param f the field in which the mouse has been clicked
* @param origBounds the field's original bounds
* @see Designer#putDown
*/
void stopStretching(FieldWidget f, jimm.datavision.field.Rectangle origBounds)
{
    designer.stopStretching(f, origBounds);
}

/**
* Tells the window to drag (move, resize) all selected fields. Called
* from one field widget when it's being manipulated with the mouse.
*
* @param action a <code>FieldWidget.ACTION_*</code> constant
* @param mouseScreenPos the location of the mouse in screen coordinates
* @see FieldWidget#mouseDragged
* @see Designer#dragSelectedWidgets
*/
void dragSelectedWidgets(int action, java.awt.Point mouseScreenPos) {
    designer.dragSelectedWidgets(action, mouseScreenPos);
}

/**
* Selects or deselcts a field widget, possibly deselecting all others
* everywhere. Called from field widget itself, this passes the request
* on to the design window.
*
* @param fieldWidget a field widget
* @param makeSelected if <code>true</code>, select this field; else
* deselect it
* @param deselectOthers if <code>true</code>, all other fields in all
* sections are deselected first
* @see Designer#select
*/
void select(FieldWidget fieldWidget, boolean makeSelected,
      boolean deselectOthers)
{
    designer.select(fieldWidget, makeSelected, deselectOthers);
}

/**
* Deselects all fields in all sections. Tells the design window to do
* so.
*
* @see Designer#deselectAll
*/
void deselectAll() {
    designer.deselectAll();
}

/**
* Adds field widget to panel. Does not affect models. Field retains its
* selection state.
*
* @param fw field widget to add
*/
public void addField(FieldWidget fw) {
    fieldPanel.add(fw.getComponent(), 0); // Add to top of visual stack.
    fw.sectionWidget = this;
    fw.getComponent().setBackground(section.isHidden()
            ? SUPPRESSED_COLOR : NORMAL_COLOR);
    growToFit();
}

/**
* Removes field widget from panel, but do not change field model's relation
* with section model. Field retains its selection state.
* <p>
* To delete a field widget completely, see {@link
* Designer#deleteSelectedFields}.
*
* @param fw field widget to remove
* @see #addField
*/
public void removeField(FieldWidget fw) {
    fieldPanel.remove(fw.getComponent());
}

public SectionFieldPanel getFieldPanel() { return fieldPanel; }

/**
* Asks the design window to snap the rectangle to it's grid.
*
* @param r a rectangle
*/
void snapToGrid(jimm.datavision.field.Rectangle r) {
    designer.snapToGrid(r);
}

/**
* Sets the visibility of all selected fields plus the one passed in.
* Passes the buck to the design window.
*
* @see FieldWidget#toggleVisibility
* @see Designer#setFieldVisibility
*/
void setFieldVisibility(boolean newVisiblity, FieldWidget fw) {
    designer.setFieldVisibility(newVisiblity, fw);
}

/**
* Asks design window to create and accepts a new text field.
*
* @see Designer#createNewTextField
*/
void createNewTextField(MouseEvent e) {
    designer.createNewTextField(this, e);
}

/**
* Displays popup menu, after enabling and disabling menu items.
*
* @param e mouse event that caused popup to do its thing
*/
void showPopup(MouseEvent e) {
    enablePopupMenuItems();
    popup.show(e.getComponent(), e.getX(), e.getY());
}

}
TOP

Related Classes of jimm.datavision.gui.SectionWidget

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.