1
28 package demo.view.hierarchy;
29
30 import y.view.ImageNodePainter;
31 import y.view.GenericNodeRealizer;
32 import y.view.HitInfo;
33 import y.view.Graph2DViewActions;
34 import y.view.ViewMode;
35 import y.view.Graph2D;
36 import y.view.NodeRealizer;
37 import y.view.NodeLabel;
38 import y.view.ShapeNodePainter;
39 import y.view.hierarchy.DefaultGenericAutoBoundsFeature;
40 import y.view.hierarchy.GenericGroupNodeRealizer;
41 import y.view.hierarchy.DefaultHierarchyGraphFactory;
42 import y.view.hierarchy.HierarchyManager;
43 import y.base.Node;
44 import y.geom.YInsets;
45
46 import java.awt.EventQueue;
47 import java.awt.Font;
48 import java.awt.Color;
49 import java.awt.Dimension;
50 import java.awt.geom.Dimension2D;
51 import java.awt.event.ActionEvent;
52 import java.net.URL;
53 import java.util.Locale;
54 import java.util.Map;
55 import javax.swing.ActionMap;
56 import javax.swing.Action;
57
58 import demo.view.DemoBase;
59
60
66 public class CustomGroupVisualizationDemo extends GroupingDemo {
67
70 private static final String CONFIGURATION_GROUP =
71 "CustomGroupVisualizationDemo_GROUP_NODE";
72
75 private static final String CONFIGURATION_FOLDER =
76 "CustomGroupVisualizationDemo_FOLDER_NODE";
77
78 protected void loadInitialGraph() {
79 loadGraph(getResource("resource/CustomGroupVisualizationDemo.graphml"));
80 }
81
82
86 protected void registerViewModes() {
87 super.registerViewModes();
88 view.addViewMode(new StateChangeViewMode());
89 }
90
91
95 protected void configureDefaultGroupNodeRealizers() {
96 final GenericNodeRealizer.Factory factory = GenericNodeRealizer.getFactory();
97
98 final Map folderImpls = factory.createDefaultConfigurationMap();
100 configureFolderNodes(folderImpls);
101 factory.addConfiguration(CONFIGURATION_FOLDER, folderImpls);
102
103 final GenericGroupNodeRealizer fnr = new GenericGroupNodeRealizer();
104 fnr.setConfiguration(CONFIGURATION_FOLDER);
105 fnr.setGroupClosed(true);
106 configureDefaultFolderLabel(fnr.getLabel());
107
108
109 final Map groupImpls = factory.createDefaultConfigurationMap();
111 configureGroupNodes(groupImpls);
112 factory.addConfiguration(CONFIGURATION_GROUP, groupImpls);
113
114 final GenericGroupNodeRealizer gnr = new GenericGroupNodeRealizer();
115 gnr.setFillColor(new Color(202, 227, 255));
116 gnr.setConfiguration(CONFIGURATION_GROUP);
117 gnr.setGroupClosed(false);
118 configureDefaultGroupLabel(gnr.getLabel());
119
120
121 final DefaultHierarchyGraphFactory hgf =
123 (DefaultHierarchyGraphFactory) getHierarchyManager().getGraphFactory();
124 hgf.setProxyNodeRealizerEnabled(true);
125 hgf.setDefaultGroupNodeRealizer(gnr);
126 hgf.setDefaultFolderNodeRealizer(fnr);
127 }
128
129
135 protected void configureGroupNodes( final Map impls ) {
136 final ShapeNodePainter painter = new ShapeNodePainter(ShapeNodePainter.ROUND_RECT);
137 impls.put(GenericNodeRealizer.Painter.class, painter);
138 impls.put(GenericNodeRealizer.ContainsTest.class, painter);
139
140 configureBoundsAndSizeHandling(impls);
141 }
142
143
148 protected void configureFolderNodes( final Map impls ) {
149 final String resource = "resource/yicon.png";
150 final URL folderUrl = getResource(DemoBase.class, resource);
151 if (folderUrl == null) {
152 throw new IllegalStateException("Could not find \"" + resource + "\".");
153 } else {
154 final ImageNodePainter painter = new ImageNodePainter(folderUrl);
155 impls.put(GenericNodeRealizer.Painter.class, painter);
156 impls.put(GenericNodeRealizer.ContainsTest.class, painter);
157
158 configureBoundsAndSizeHandling(impls);
159 }
160 }
161
162
166 private void configureDefaultFolderLabel( final NodeLabel fnl ) {
167 fnl.setFontSize(14);
168 fnl.setFontStyle(Font.BOLD);
169 fnl.setTextColor(Color.WHITE);
170 fnl.setAutoSizePolicy(NodeLabel.AUTOSIZE_NODE_WIDTH);
171 fnl.setBackgroundColor(new Color(62, 66, 69));
172 fnl.setModel(NodeLabel.SANDWICH);
173 fnl.setPosition(NodeLabel.S);
174 }
175
176
180 private void configureDefaultGroupLabel( final NodeLabel gnl ) {
181 gnl.setFontSize(14);
182 gnl.setFontStyle(Font.BOLD);
183 gnl.setTextColor(Color.WHITE);
184 gnl.setAutoSizePolicy(NodeLabel.AUTOSIZE_CONTENT);
185 gnl.setBackgroundColor(null);
186 gnl.setRotationAngle(270);
187 gnl.setPosition(NodeLabel.BOTTOM_LEFT);
188 }
189
190
195 private void configureBoundsAndSizeHandling( final Map map ) {
196 final DefaultGenericAutoBoundsFeature abf = new DefaultGenericAutoBoundsFeature() {
197
205 public YInsets getAutoBoundsInsets( final NodeRealizer context ) {
206 if (accept(context)) {
207 final YInsets insets =
208 ((GenericGroupNodeRealizer) context).getMinimalInsets();
209 return new YInsets(
210 insets.top,
211 Math.max(insets.left, context.getLabel().getWidth() + 5),
212 insets.bottom,
213 insets.right
214 );
215 }
216
217 return super.getInsets(context);
218 }
219
220
228 protected Dimension2D calculateMinimalLabelSize( final NodeRealizer context ) {
229 if (accept(context)) {
230 final NodeLabel label = context.getLabel();
231 final double d = 2*label.getDistance();
232 return new Dimension(
235 (int) Math.ceil(label.getContentHeight() + d),
236 (int) Math.ceil(label.getContentWidth() + d));
237 }
238
239 return super.calculateMinimalLabelSize(context);
240 }
241
242
249 private boolean accept( final NodeRealizer context ) {
250 if (context instanceof GenericGroupNodeRealizer) {
251 GenericGroupNodeRealizer ggnr = ((GenericGroupNodeRealizer) context);
252 if (ggnr.labelCount() > 0) {
253 final NodeLabel nl = ggnr.getLabel();
254 if (nl.getModel() == NodeLabel.INTERNAL &&
255 nl.getPosition() == NodeLabel.BOTTOM_LEFT &&
256 nl.getRotationAngle() == 270) {
257 return true;
258 }
259 }
260 }
261
262 return false;
263 }
264 };
265 abf.setConsiderNodeLabelSize(true);
266 map.put(GenericGroupNodeRealizer.GenericAutoBoundsFeature.class, abf);
267 map.put(GenericNodeRealizer.GenericSizeConstraintProvider.class, abf);
268 map.put(GenericNodeRealizer.LabelBoundsChangedHandler.class, abf);
269 }
270
271
272
273 public static void main( String[] args ) {
274 EventQueue.invokeLater(new Runnable() {
275 public void run() {
276 Locale.setDefault(Locale.ENGLISH);
277 initLnF();
278 (new CustomGroupVisualizationDemo()).start();
279 }
280 });
281 }
282
283
284
288 private static final class StateChangeViewMode extends ViewMode {
289 public void mouseClicked( final double x, final double y ) {
290 if (lastClickEvent.getClickCount() == 2 &&
291 lastClickEvent.getButton() == 1) {
292 final HitInfo hitInfo = getHitInfo(x, y);
293 if (hitInfo.hasHitNodes()) {
294 final Node node = hitInfo.getHitNode();
295 final Graph2D graph = getGraph2D();
296 final HierarchyManager manager = graph.getHierarchyManager();
297 if (manager != null) {
298 if (manager.isGroupNode(node)) {
299 closeGroup(graph, node);
300 } else if (manager.isFolderNode(node)) {
301 openFolder(graph, node);
302 }
303 }
304 }
305 }
306 }
307
308
313 protected void closeGroup( final Graph2D graph, final Node node ) {
314 Action action = null;
315
316 final ActionMap amap = view.getCanvasComponent().getActionMap();
317 if (amap != null) {
318 action = amap.get(Graph2DViewActions.CLOSE_GROUPS);
319 }
320 if (action == null) {
321 action = new Graph2DViewActions.CloseGroupsAction();
322 }
323
324 view.getGraph2D().unselectAll();
325 view.getGraph2D().setSelected(node, true);
326 action.actionPerformed(new ActionEvent(view, ActionEvent.ACTION_PERFORMED, ""));
327 }
328
329
334 protected void openFolder( final Graph2D graph, final Node node ) {
335 Action action = null;
336
337 final ActionMap amap = view.getCanvasComponent().getActionMap();
338 if (amap != null) {
339 action = amap.get(Graph2DViewActions.OPEN_FOLDERS);
340 }
341 if (action == null) {
342 action = new Graph2DViewActions.OpenFoldersAction();
343 }
344
345 view.getGraph2D().unselectAll();
346 view.getGraph2D().setSelected(node, true);
347 action.actionPerformed(new ActionEvent(view, ActionEvent.ACTION_PERFORMED, ""));
348 }
349 }
350 }
351