Class BaseView

All Implemented Interfaces:
IFeedbackProvider, IFileDropHandler, ComponentListener, FocusListener, MouseListener, ImageObserver, MenuContainer, Serializable, EventListener, Accessible, RootPaneContainer, WindowConstants
Direct Known Subclasses:
DrawingView, GeometrySliceDemoView, JsonView, LogView, MapView2D, NetworkLayoutDemoView, PlotView, SimulationView, VirtualView

Base class for all MDI views.

A BaseView is a JInternalFrame hosted on the application's Desktop. Most views contain an IContainer that provides a "world" coordinate system and drawing/interaction support. Container-less views (e.g. log or config panels) are also supported.

Persistence key (VIEWPROPNAME)

Each view owns a stable string prefix used as the namespace for its persisted properties (position, size, visibility, etc.). The prefix is derived automatically from the view's title at construction time by sanitizeForKey(String). Subclasses that need a hand-chosen, title-independent key should override getPropertyName().

Why not use the title directly? Titles may contain spaces and special characters that are awkward inside XML property keys, and they can change between releases. The sanitised form is stable and safe.

Persistence format

Properties are written using dotted keys: prefix.x, prefix.y, prefix.w, prefix.h, prefix.visible, prefix.maximized. When reading back, the legacy non-dotted variants (e.g. prefixx, prefixvisible) are also accepted so that files saved by older versions of the framework continue to work.

File drag-and-drop

Drop support is activated by calling enableFileDrop(Predicate) in the subclass constructor (after super(...)). That single call installs a FileDropHandler on every appropriate surface — the container canvas, the scroll-pane viewport (when present), and the frame itself — and stores the filter. Subclasses then override filesDropped(List) to handle the accepted files. No other wiring is required.

 public MyView(Object... keyVals) {
     super(PropertyUtils.fromKeyValues(keyVals));
     enableFileDrop(f -> f.getName().endsWith(".csv"));
 }

 @Override
 public void filesDropped(List<File> files) {
     openCsvFile(files.get(0));
 }
 

Design notes

  • All property parsing happens once in BaseView.ViewInitConfig.from(java.util.Properties), keeping the constructor body straightforward.
  • Nested static helpers (BaseView.FrameConfigurer, BaseView.ViewContentBuilder, etc.) keep each responsibility isolated without requiring separate compilation units.
See Also:
  • Field Details

    • VIEWPROPNAME

      protected String VIEWPROPNAME
      Stable prefix used to namespace this view's persisted properties.

      Set during construction from the sanitised view title. Subclasses that want an explicit, title-independent key should override getPropertyName() rather than writing to this field.

    • infoDialog

      protected JDialog infoDialog
      Lazily-shown dialog displaying view information.
    • properties

      protected final Properties properties
      Properties supplied at construction time. Also used as a lightweight per-view key-value store by setBooleanProperty(java.lang.String, boolean) etc.
    • desktop

      protected final JDesktopPane desktop
      The desktop pane that hosts this internal frame.
    • container

      protected IContainer container
      Optional world-coordinate container; null for container-less views.
    • scrollPane

      protected JScrollPane scrollPane
      Optional scroll pane wrapping the container component.
    • viewPopupMenu

      protected final ViewPopupMenu viewPopupMenu
      Right-click popup menu for this view.
    • virtualItem

      protected VirtualWindowItem virtualItem
      Optional thumbnail item shown in the VirtualView. Set externally by the virtual desktop machinery.
    • statusWP

      protected Point2D.Double statusWP
  • Constructor Details

    • BaseView

      public BaseView(Object... keyVals)
      Construct a BaseView from alternating key/value property pairs.
      Parameters:
      keyVals - alternating PropertyUtils key/value pairs
    • BaseView

      public BaseView(ViewOptions options)
      Construct a view from an immutable typed configuration.

      The options are defensively copied before initialization. This overload is additive; existing key/value and Properties constructors retain their behavior.

      Parameters:
      options - view initialization options; must not be null
      Throws:
      NullPointerException - if options is null
    • BaseView

      public BaseView(Properties props)
      Construct a BaseView from a pre-built Properties object.
      Parameters:
      props - configuration properties; must not be null
  • Method Details

    • resolveContainer

      protected IContainer resolveContainer(Rectangle2D.Double worldSystem)
      Resolve the IContainer for this view.

      Resolution order:

      1. An IContainer instance stored directly in the properties under PropertyUtils.CONTAINER.
      2. A Class stored under PropertyUtils.CONTAINERCLASS, instantiated via its (Rectangle2D.Double) constructor.
      3. A default BaseContainer.
      Parameters:
      worldSystem - the initial world coordinate rectangle
      Returns:
      a non-null container
    • onFirstRealize

      public void onFirstRealize()
      Called exactly once, after the view has been fully constructed and registered with the ViewManager.

      For eagerly-created views this occurs during normal startup. For lazily-created views (see ViewConfiguration) it occurs the first time the user selects the view from the Views menu.

      The default implementation is a no-op. Subclasses may override to reconcile with shared application state or perform other one-time post-construction work.

    • getInsets

      public Insets getInsets()
      Slightly reduces the bottom inset to match legacy appearance.
      Overrides:
      getInsets in class JComponent
      Returns:
      adjusted insets
    • prepareForExit

      public void prepareForExit()
      Called when the application is about to exit.

      Delegates to IContainer.prepareForExit() if a container is present, allowing simulations or background tasks to stop cleanly.

    • getParentFrame

      public JFrame getParentFrame()
      Returns the top-level JFrame that hosts the desktop, resolving it lazily on first call.
      Returns:
      the parent frame, or null if not yet in a realized hierarchy
    • getIContainer

      public IContainer getIContainer()
      Returns the container hosted by this view.
      Returns:
      the container, or null for container-less views
    • enableFileDrop

      protected final void enableFileDrop()
      Activate file drag-and-drop for this view, accepting all dropped files.

      Equivalent to enableFileDrop(null). Every file the user drops on the view is forwarded to filesDropped(java.util.List<java.io.File>) without any filtering.

      Call this from the subclass constructor after super(...).

      See Also:
    • enableFileDrop

      protected final void enableFileDrop(Predicate<File> filter)
      Activate file drag-and-drop for this view with a type filter.

      Installs a single FileDropHandler instance on every surface that can realistically receive a drop in this view:

      1. Container canvas — the primary drawing surface for container-backed views.
      2. Scroll-pane and its viewport — present when the view was constructed with a scroll pane; without this, drops on the scroll-bar gutters would be silently ignored.
      3. The view frame itself — a fallback that covers container-less views (e.g. log or config panels) and any area of the frame chrome not covered by the surfaces above.

      The supplied filter is stored via setFileFilter(java.util.function.Predicate<java.io.File>) and is evaluated by FileDropHandler before filesDropped(java.util.List<java.io.File>) is called. Files that do not match the filter are silently discarded; if every file in a drop is rejected, Swing renders the "no-drop" cursor so the user receives clear feedback.

      Usage pattern — call once from the subclass constructor, then override filesDropped(java.util.List<java.io.File>):

       public MyView(Object... keyVals) {
           super(PropertyUtils.fromKeyValues(keyVals));
           enableFileDrop(f -> f.getName().endsWith(".csv"));
       }
      
       @Override
       public void filesDropped(List<File> files) {
           openCsvFile(files.get(0));
       }
       

      This method is final to guarantee that the surface coverage described above is always complete. Subclasses that need finer control (e.g. canvas-only drops) may call JComponent.setTransferHandler(javax.swing.TransferHandler) directly after calling this method.

      Parameters:
      filter - acceptance predicate applied to each dropped file; pass null to accept all files without screening
    • setFileFilter

      public void setFileFilter(Predicate<File> filter)
      Set the file filter used to screen dropped files.

      Prefer calling enableFileDrop(Predicate) rather than this method directly; enableFileDrop both stores the filter and installs the FileDropHandler on all required surfaces. This setter is part of the IFileDropHandler contract and is also useful when the filter needs to be swapped at runtime without reinstalling the handler.

      Specified by:
      setFileFilter in interface IFileDropHandler
      Parameters:
      filter - the acceptance predicate, or null to accept all files
    • getFileFilter

      public Predicate<File> getFileFilter()
      Returns the current file filter, or null if none is set.
      Specified by:
      getFileFilter in interface IFileDropHandler
      Returns:
      the acceptance predicate
    • filesDropped

      public void filesDropped(List<File> files)
      Called on the EDT when one or more accepted files are dropped on this view.

      The default implementation is a no-op. Subclasses that have called enableFileDrop(Predicate) should override this method to handle the dropped files. The list is never null and is never empty; the filter (if any) has already been applied.

      Specified by:
      filesDropped in interface IFileDropHandler
      Parameters:
      files - the accepted dropped files; never null, never empty
    • getName

      public String getName()
      Returns the view title (legacy: Component.getName() maps to the title for backward compatibility).
      Overrides:
      getName in class Component
      Returns:
      the title
    • getPropertyName

      public String getPropertyName()
      Returns the stable property-key prefix used to namespace this view's persisted state.

      By default this is derived automatically from the view title via sanitizeForKey(String). Subclasses that require a fixed, title-independent key should override this method:

       @Override
       public String getPropertyName() { return "myMapView"; }
       
      Returns:
      the persistence key prefix; never null
    • getViewPopupMenu

      public ViewPopupMenu getViewPopupMenu()
      Returns the right-click popup menu for this view.
      Returns:
      the popup menu; never null
    • isScrollable

      public boolean isScrollable()
      Returns true if this view wraps its container in a scroll pane.
      Returns:
      true if scrollable
    • getScrollPane

      public JScrollPane getScrollPane()
      Returns the scroll pane, if this view was configured as scrollable.
      Returns:
      the scroll pane, or null
    • rightClicked

      public boolean rightClicked(MouseEvent mouseEvent)
      Optional hook for subclasses: called on a right-click. The default returns false (not handled).
      Parameters:
      mouseEvent - the triggering event
      Returns:
      true if the event was handled and should not be processed further
    • refresh

      public void refresh()
      Refresh the view by delegating to the container, if the view is currently visible.
    • isViewVisible

      public boolean isViewVisible()
      Returns true if any part of this internal frame's bounds intersects the parent desktop's bounds, indicating that it is on-screen.
      Returns:
      true if visible in the desktop
    • isOnTop

      public boolean isOnTop()
      Returns true if this view is at the top of the desktop's z-order.
      Returns:
      true if on top
    • getSpecialClip

      public Shape getSpecialClip()
      Returns an optional clip shape used by the rendering pipeline. The default returns null.
      Returns:
      a clip shape, or null
    • offset

      public void offset(int dh, int dv)
      Move this view by the specified pixel offset.
      Parameters:
      dh - horizontal offset in pixels (positive = right)
      dv - vertical offset in pixels (positive = down)
    • center

      public void center()
      center this view within its parent frame.

      This is a no-op if the parent frame cannot be determined.

    • getToolBar

      public AToolBar getToolBar()
      Returns the toolbar for this view, or null if none was configured.
      Returns:
      the toolbar
    • initFeedback

      protected FeedbackPane initFeedback()
      Create and install a feedback pane with default colors (cyan on black, 9 pt font).
      Returns:
      the created feedback pane
    • initFeedback

      protected FeedbackPane initFeedback(Color fg, Color bg, int fontSize)
      Create and install a feedback pane with custom colors and font size.
      Parameters:
      fg - foreground color
      bg - background color
      fontSize - font size in points
      Returns:
      the created feedback pane
      Throws:
      IllegalStateException - if this view has no container
    • getFeedbackStrings

      public void getFeedbackStrings(IContainer container, Point pp, Point2D.Double wp, List<String> feedbackStrings)
      Default feedback implementation: no-op. Subclasses override to provide coordinate or status strings.
      Specified by:
      getFeedbackStrings in interface IFeedbackProvider
      Parameters:
      container - the container.
      pp - the mouse location.
      wp - the corresponding world point.
      feedbackStrings - the List of feedback strings to add to.
    • getVirtualItem

      public VirtualWindowItem getVirtualItem()
      Returns the virtual-desktop thumbnail item associated with this view, or null if the virtual desktop is not active.
      Returns:
      the virtual window item
    • setVirtualItem

      public void setVirtualItem(VirtualWindowItem virtualItem)
      Set the virtual-desktop thumbnail item.
      Parameters:
      virtualItem - the item to associate with this view
    • applyFocusFix

      public static void applyFocusFix(JMenu menu, BaseView view)
      Install a mouse-enter listener on menu that selects view when the mouse enters the menu.

      This works around a focus issue on some platforms where the view's menu bar flashes or loses focus when a menu is opened. Selecting the internal frame explicitly prevents the flash.

      Parameters:
      menu - the menu to attach the listener to
      view - the view to select on mouse entry
    • handleMagnify

      public void handleMagnify(MouseEvent me)
      Handle a magnify (modifier + mouse) request.

      Dispatches to the EDT if not already on it.

      Parameters:
      me - the triggering mouse event
    • viewInfo

      public void viewInfo()
      Show the view information dialog.

      If the subclass provides an AbstractViewInfo via getViewInfo() that is displayed in a dialog; otherwise a generic "no information available" message is shown.

    • getInfoButton

      public ViewInfoButton getInfoButton()
      Returns a button that triggers the view info dialog when clicked. This is primarily for views that don't have a toolbar where the user might expect to find an info button, but it can be used by any view.
      Returns:
      the info button
    • getViewInfo

      public AbstractViewInfo getViewInfo()
      Override to supply structured information for the info dialog. The default returns null (no info available).
      Returns:
      view info, or null
    • getImageComponent

      public Component getImageComponent()
      The component that best represents this view as a static image, for screenshot/clipboard capture (see TakePicture).

      The default returns the container's drawable component, which is correct for ordinary item-based 2D views: for those, the container component already shows everything the view has to offer. Views whose visible content is not fully contained in that one component should override this. PlotView is the prototypical example: its title, legend, and axis labels live on the surrounding PlotPanel, not on the inner PlotCanvas the container exposes, so capturing the container component alone would silently drop them.

      This exists so callers that want "an image of this view" — a toolbar's camera button, a menu action, a future export feature — have one consistent, view-owned question to ask, instead of each caller re-deriving its own answer (or a shared utility like TakePicture having to special-case specific view/panel types itself).

      Returns:
      the component to capture as this view's image; the container's component if one is present, otherwise this view itself
    • setFromProperties

      public void setFromProperties(Properties properties)
      Restore this view's state from a properties map previously produced by getConfigurationProperties().

      Both the current dotted key format (prefix.x) and the legacy non-dotted format (prefixx) are recognised, so files written by older versions of the framework load correctly.

      Parameters:
      properties - the source properties; may be null
    • getConfigurationProperties

      public Properties getConfigurationProperties()
      Capture this view's current state into a Properties object.

      Keys use the dotted format: prefix.x, prefix.y, prefix.w, prefix.h, prefix.visible, prefix.maximized. The prefix is getPropertyName().

      Returns:
      a non-null properties object containing this view's state
    • getProperties

      public Properties getProperties()
      Returns the properties that were used to construct this view.
      Returns:
      the construction-time properties; never null
    • checkBooleanProperty

      public boolean checkBooleanProperty(String key)
      Read a boolean property from this view's internal properties.
      Parameters:
      key - the property key
      Returns:
      the value, or false if absent or unparseable
    • setBooleanProperty

      public void setBooleanProperty(String key, boolean val)
      Store a boolean property in this view's internal properties.
      Parameters:
      key - the property key
      val - the value
    • getIntProperty

      public int getIntProperty(String key)
      Read an integer property from this view's internal properties.
      Parameters:
      key - the property key
      Returns:
      the value, or -1 if absent or unparseable
    • setIntProperty

      public void setIntProperty(String key, int val)
      Store an integer property in this view's internal properties.
      Parameters:
      key - the property key
      val - the value
    • focusGained

      public void focusGained(FocusEvent e)
      Specified by:
      focusGained in interface FocusListener
    • focusLost

      public void focusLost(FocusEvent e)
      Specified by:
      focusLost in interface FocusListener
    • mouseClicked

      public void mouseClicked(MouseEvent e)
      Specified by:
      mouseClicked in interface MouseListener
    • mousePressed

      public void mousePressed(MouseEvent e)
      Specified by:
      mousePressed in interface MouseListener
    • mouseReleased

      public void mouseReleased(MouseEvent e)
      Specified by:
      mouseReleased in interface MouseListener
    • mouseEntered

      public void mouseEntered(MouseEvent e)
      Specified by:
      mouseEntered in interface MouseListener
    • mouseExited

      public void mouseExited(MouseEvent e)
      Close the magnify window when the mouse leaves any view canvas.
      Specified by:
      mouseExited in interface MouseListener
    • componentHidden

      public void componentHidden(ComponentEvent e)
      Specified by:
      componentHidden in interface ComponentListener
    • componentShown

      public void componentShown(ComponentEvent e)
      Specified by:
      componentShown in interface ComponentListener
    • componentMoved

      public void componentMoved(ComponentEvent e)
      No-op: FlatLaf repaints correctly on move without explicit desktop repaint calls. Retained for API continuity.
      Specified by:
      componentMoved in interface ComponentListener
    • componentResized

      public void componentResized(ComponentEvent e)
      No-op: FlatLaf repaints correctly on resize. Retained for API continuity.
      Specified by:
      componentResized in interface ComponentListener
    • addWestPanel

      public void addWestPanel(JComponent panel)
      Adds a component to the WEST slot of this view's content pane, expanding the frame width to accommodate it.

      Uses a double invokeLater to guarantee execution after all construction-time invokeLater calls have been processed — including BaseView's deferred setVisible and ViewConfiguration's placement call. A single invokeLater is not sufficient because the placement work is itself queued at the same EDT level as a naive single defer.

      Parameters:
      panel - the component to place in the WEST slot; must not be null
    • getAnnotationLayer

      public Layer getAnnotationLayer()
      Helper method to the the annotation layer from the container, if available.
      Returns:
      the annotation layer, or null if no container or annotation layer is available
    • getConnectionLayer

      public Layer getConnectionLayer()
      Helper method to the get the connection layer from the container, if available.
      Returns:
      the connection layer, or null if no container or connection layer is available
    • getDefaultLayer

      public Layer getDefaultLayer()
      Helper method to the get the default layer from the container, if available.
      Returns:
      the default layer, or null if no container or default layer is available
    • setAfterDraw

      public void setAfterDraw(IDrawable afterDraw)
      Helper method to set the after-draw layer in the container, if available.
      Parameters:
      afterDraw - the drawable to set as the after-draw layer
    • setBeforeDraw

      public void setBeforeDraw(IDrawable beforeDraw)
      Helper method to set the before-draw layer in the container, if available.
      Parameters:
      beforeDraw - the drawable to set as the before-draw layer
    • hoverUpdate

      public void hoverUpdate(HoverEvent he)
      Handle a hover event.

      Subclasses can override this method to respond to hover events, which are triggered by mouse movement with no buttons down. The default implementation is a no-op.

      Parameters:
      he - the hover event
    • hoverClosed

      public void hoverClosed(HoverEvent he)
      Handle the closing (dismissal) of a hover popup/tooltip.

      Subclasses can override this method to respond when a hover previously reported via hoverUpdate(edu.cnu.mdi.hover.HoverEvent) has ended. The default implementation is a no-op.

      Parameters:
      he - the hover event
    • getCenterComponent

      protected Component getCenterComponent()
      Returns the Component currently in the CENTER position of the content pane,
      Returns:
      The Component in the CENTER position, or null if empty or if the layout manager was changed from BorderLayout.