All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.googlecode.blaisemath.graphics.swing.JGraphicRoot Maven / Gradle / Ivy

There is a newer version: 3.0.16
Show newest version
/*
 * GraphicRoot.java
 * Created Jan 12, 2011
 */

package com.googlecode.blaisemath.graphics.swing;

/*
 * #%L
 * BlaiseGraphics
 * --
 * Copyright (C) 2009 - 2019 Elisha Peterson
 * --
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import com.google.common.base.Objects;
import com.googlecode.blaisemath.graphics.core.GMouseEvent;
import com.googlecode.blaisemath.graphics.core.Graphic;
import com.googlecode.blaisemath.graphics.core.GraphicComposite;
import com.googlecode.blaisemath.graphics.core.GraphicUtils;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.googlecode.blaisemath.style.StyleContext;
import com.googlecode.blaisemath.style.Styles;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Point2D;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.swing.JPopupMenu;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;

/**
 * 

* Manages the entries on a {@link JGraphicComponent}. * The primary additional behavior implemented by {@code GraphicRoot}, beyond that of its parent * {@code GraphicComposite}, is listening to mouse events on the component and * generating {@link GMouseEvent}s from them. *

*

* Subclasses might provide additional behavior such as (i) caching the shapes to be drawn * to avoid expensive recomputation, or (ii) sorting the shapes into an alternate draw order * (e.g. for projections from 3D to 2D). *

* * @author Elisha */ public final class JGraphicRoot extends GraphicComposite { /** Parent component upon which the graphics are drawn. */ protected final JGraphicComponent owner; /** Context menu for actions on the graphics */ protected final JPopupMenu popup = new JPopupMenu(); /** Provides a pluggable way to generate mouse events */ @Nonnull protected GMouseEvent.Factory mouseFactory = new GMouseEvent.Factory(); /** Current owner of mouse events. Gets first priority for mouse events that occur. */ private transient Graphic mouseGraphic = null; /** Tracks current mouse location */ private transient Point2D mouseLoc = null; /** * Construct a default instance * @param component the graphic root's component */ public JGraphicRoot(JGraphicComponent component) { this.owner = checkNotNull(component); MouseHandler mh = new MouseHandler(); this.owner.addMouseListener(mh); this.owner.addMouseMotionListener(mh); this.owner.setComponentPopupMenu(popup); // set up style setStyleContext(Styles.defaultStyleContext()); style.put(Styles.FILL, Color.lightGray); style.put(Styles.STROKE, Color.black); // set up popup menu popup.addPopupMenuListener(new PopupMenuListener(){ @Override public void popupMenuWillBecomeVisible(PopupMenuEvent e) { if (mouseLoc != null) { popup.removeAll(); Set> selected = owner.isSelectionEnabled() ? owner.getSelectionModel().getSelection() : null; initContextMenu(popup, null, mouseLoc, null, selected); if (popup.getComponentCount() == 0) { // cancel popup } } } @Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { popup.removeAll(); } @Override public void popupMenuCanceled(PopupMenuEvent e) { popup.removeAll(); } }); } // // // PROPERTY PATTERNS // @Override public void setParent(GraphicComposite p) { checkArgument(p == null, "GraphicRoot cannot be added to another GraphicComposite"); } @Override public void setStyleContext(StyleContext rend) { checkArgument(rend != null, "GraphicRoot must have a non-null StyleProvider!"); super.setStyleContext(rend); } /** * Return current object used to generate mouse events. * @return mouse event factory */ public GMouseEvent.Factory getMouseEventFactory() { return mouseFactory; } /** * Modifies how mouse events are created. * @param factory responsible for generating mouse events */ public void setMouseEventFactory(GMouseEvent.Factory factory) { if (this.mouseFactory != factory) { this.mouseFactory = checkNotNull(factory); } } // // // EVENT HANDLING // @Override protected void fireGraphicChanged() { graphicChanged(this); } @Override public void graphicChanged(Graphic source) { if (owner != null) { owner.repaint(); } } // // // MOUSE HANDLING // this code handles translation of mouse events on the component // to mouse events on the graphics // /** * Create GraphicMouseEvent from given event. * @param e mouse event * @return associated graphic mouse event */ private GMouseEvent graphicMouseEvent(MouseEvent e) { Point2D localPoint = e.getPoint(); if (owner.getInverseTransform() != null) { localPoint = owner.getInverseTransform().transform(localPoint, null); } return mouseFactory.createEvent(e, localPoint, this); } /** * Change current owner of mouse events. * @param gme graphic mouse event * @param keepCurrent whether to maintain current selection even if it's behind another graphic */ private void updateMouseGraphic(GMouseEvent gme, boolean keepCurrent) { if (keepCurrent && mouseGraphic != null && GraphicUtils.isFunctional(mouseGraphic) && mouseGraphic.contains(gme.getGraphicLocation())) { return; } Graphic nue = mouseGraphicAt(gme.getGraphicLocation()); if (!Objects.equal(mouseGraphic, nue)) { mouseExit(mouseGraphic, gme); mouseGraphic = nue; mouseEnter(mouseGraphic, gme); } } private void mouseEnter(Graphic mouseGraphic, GMouseEvent event) { if (mouseGraphic != null) { event.setGraphicSource(mouseGraphic); for (MouseListener l : mouseGraphic.getMouseListeners()) { l.mouseEntered(event); if (event.isConsumed()) { return; } } } } private void mouseExit(Graphic mouseGraphic, GMouseEvent event) { if (mouseGraphic != null) { event.setGraphicSource(mouseGraphic); for (MouseListener l : mouseGraphic.getMouseListeners()) { l.mouseExited(event); if (event.isConsumed()) { return; } } } } /** Delegate for mouse events */ private class MouseHandler implements MouseListener, MouseMotionListener { @Override public void mouseClicked(MouseEvent e) { GMouseEvent gme = graphicMouseEvent(e); updateMouseGraphic(gme, false); if (mouseGraphic != null) { for (MouseListener l : mouseGraphic.getMouseListeners()) { l.mouseClicked(gme); if (gme.isConsumed()) { return; } } } } @Override public void mouseMoved(MouseEvent e) { GMouseEvent gme = graphicMouseEvent(e); mouseLoc = gme.getGraphicLocation(); updateMouseGraphic(gme, false); if (mouseGraphic != null) { gme.setGraphicSource(mouseGraphic); for (MouseMotionListener l : mouseGraphic.getMouseMotionListeners()) { l.mouseMoved(gme); if (gme.isConsumed()) { return; } } } } @Override public void mousePressed(MouseEvent e) { GMouseEvent gme = graphicMouseEvent(e); updateMouseGraphic(gme, false); if (mouseGraphic != null) { gme.setGraphicSource(mouseGraphic); for (MouseListener l : mouseGraphic.getMouseListeners()) { l.mousePressed(gme); if (gme.isConsumed()) { return; } } } } @Override public void mouseDragged(MouseEvent e) { if (mouseGraphic != null) { GMouseEvent gme = graphicMouseEvent(e); gme.setGraphicSource(mouseGraphic); for (MouseMotionListener l : mouseGraphic.getMouseMotionListeners()) { l.mouseDragged(gme); if (gme.isConsumed()) { return; } } } } @Override public void mouseReleased(MouseEvent e) { if (mouseGraphic != null) { GMouseEvent gme = graphicMouseEvent(e); gme.setGraphicSource(mouseGraphic); for (MouseListener l : mouseGraphic.getMouseListeners()) { l.mouseReleased(gme); if (gme.isConsumed()) { return; } } } } @Override public void mouseEntered(MouseEvent e) { // no behavior desired } @Override public void mouseExited(MouseEvent e) { if (mouseGraphic != null) { GMouseEvent gme = graphicMouseEvent(e); mouseExit(mouseGraphic, gme); } } } // }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy