1/*
2 * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24package com.sun.hotspot.igv.view.widgets;
25
26import com.sun.hotspot.igv.graph.Figure;
27import com.sun.hotspot.igv.graph.OutputSlot;
28import com.sun.hotspot.igv.graph.Slot;
29import com.sun.hotspot.igv.util.DoubleClickHandler;
30import com.sun.hotspot.igv.view.DiagramScene;
31import java.awt.Color;
32import java.awt.Font;
33import java.awt.Graphics2D;
34import java.awt.Rectangle;
35import java.awt.geom.Rectangle2D;
36import java.util.HashSet;
37import java.util.Set;
38import org.netbeans.api.visual.action.WidgetAction;
39import org.netbeans.api.visual.model.ObjectState;
40import org.netbeans.api.visual.widget.Widget;
41
42/**
43 *
44 * @author Thomas Wuerthinger
45 */
46public abstract class SlotWidget extends Widget implements DoubleClickHandler {
47
48    private Slot slot;
49    private FigureWidget figureWidget;
50    private static double TEXT_ZOOM_FACTOR = 0.9;
51    private static double ZOOM_FACTOR = 0.6;
52    private DiagramScene diagramScene;
53
54    public SlotWidget(Slot slot, DiagramScene scene, Widget parent, FigureWidget fw) {
55        super(scene);
56        this.diagramScene = scene;
57        this.slot = slot;
58        figureWidget = fw;
59        this.setToolTipText("<HTML>" + slot.getToolTipText() + "</HTML>");
60        this.setCheckClipping(true);
61        parent.addChild(this);
62
63        //this.setPreferredBounds(this.calculateClientArea());
64    }
65
66    @Override
67    protected void notifyStateChanged(ObjectState previousState, ObjectState state) {
68        super.notifyStateChanged(previousState, state);
69        repaint();
70    }
71
72    public Slot getSlot() {
73        return slot;
74    }
75
76    public FigureWidget getFigureWidget() {
77        return figureWidget;
78    }
79
80    @Override
81    protected void paintWidget() {
82
83        if (getScene().getZoomFactor() < ZOOM_FACTOR) {
84            return;
85        }
86
87        Graphics2D g = this.getGraphics();
88        // g.setColor(Color.DARK_GRAY);
89        int w = this.getBounds().width;
90        int h = this.getBounds().height;
91
92        if (getSlot().getSource().getSourceNodes().size() > 0) {
93            final int SMALLER = 0;
94            g.setColor(getSlot().getColor());
95
96            int FONT_OFFSET = 2;
97
98            int s = h - SMALLER;
99            int rectW = s;
100
101            Font font = this.getSlot().getFigure().getDiagram().getSlotFont();
102            if (this.getState().isSelected()) {
103                font = font.deriveFont(Font.BOLD);
104            }
105
106            if (getSlot().getShortName() != null && getSlot().getShortName().length() > 0) {
107                g.setFont(font);
108                Rectangle2D r1 = g.getFontMetrics().getStringBounds(getSlot().getShortName(), g);
109                rectW = (int) r1.getWidth() + FONT_OFFSET * 2;
110            }
111            g.fillRect(w / 2 - rectW / 2, 0, rectW - 1, s - 1);
112
113            if (this.getState().isHighlighted()) {
114                g.setColor(Color.BLUE);
115            } else {
116                g.setColor(Color.BLACK);
117            }
118            g.drawRect(w / 2 - rectW / 2, 0, rectW - 1, s - 1);
119
120            if (getSlot().getShortName() != null && getSlot().getShortName().length() > 0 && getScene().getZoomFactor() >= TEXT_ZOOM_FACTOR) {
121                Rectangle2D r1 = g.getFontMetrics().getStringBounds(getSlot().getShortName(), g);
122                g.drawString(getSlot().getShortName(), (int) (w - r1.getWidth()) / 2, g.getFontMetrics().getAscent() - 1);//(int) (r1.getHeight()));
123            }
124
125        } else {
126
127            if (this.getSlot().getConnections().isEmpty()) {
128                if (this.getState().isHighlighted()) {
129                    g.setColor(Color.BLUE);
130                } else {
131                    g.setColor(Color.BLACK);
132                }
133                int r = 2;
134                if (slot instanceof OutputSlot) {
135                    g.fillOval(w / 2 - r, Figure.SLOT_WIDTH - Figure.SLOT_START - r, 2 * r, 2 * r);
136                } else {
137                    g.fillOval(w / 2 - r, Figure.SLOT_START - r, 2 * r, 2 * r);
138                }
139            } else {
140                // Do not paint a slot with connections.
141            }
142        }
143    }
144
145    @Override
146    protected Rectangle calculateClientArea() {
147        return new Rectangle(0, 0, slot.getWidth(), Figure.SLOT_WIDTH);
148    }
149
150    protected abstract int calculateSlotWidth();
151
152    protected int calculateWidth(int count) {
153        return getFigureWidget().getFigure().getWidth() / count;
154    }
155
156    @Override
157    public void handleDoubleClick(Widget w, WidgetAction.WidgetMouseEvent e) {
158        Set<Integer> hiddenNodes = new HashSet<>(diagramScene.getModel().getHiddenNodes());
159        if (diagramScene.isAllVisible()) {
160            hiddenNodes = new HashSet<>(diagramScene.getModel().getGraphToView().getGroup().getAllNodes());
161        }
162
163        boolean progress = false;
164        for (Figure f : diagramScene.getModel().getDiagramToView().getFigures()) {
165            for (Slot s : f.getSlots()) {
166                if (DiagramScene.doesIntersect(s.getSource().getSourceNodesAsSet(), slot.getSource().getSourceNodesAsSet())) {
167                    progress = true;
168                    hiddenNodes.removeAll(f.getSource().getSourceNodesAsSet());
169                }
170            }
171        }
172
173        if (progress) {
174            this.diagramScene.getModel().showNot(hiddenNodes);
175        }
176    }
177}
178