1
14 package demo.view.layout.genealogy;
15
16 import demo.view.DemoBase;
17 import demo.view.layout.genealogy.iohandler.GedcomHandler;
18 import y.base.DataProvider;
19 import y.base.Node;
20 import y.base.NodeList;
21 import y.base.NodeMap;
22 import y.io.GMLIOHandler;
23 import y.layout.genealogy.FamilyTreeLayouter;
24 import y.module.FamilyTreeLayoutModule;
25 import y.util.D;
26 import y.util.DataProviderAdapter;
27 import y.util.GraphHider;
28 import y.view.BendList;
29 import y.view.BevelNodePainter;
30 import y.view.BridgeCalculator;
31 import y.view.DefaultGraph2DRenderer;
32 import y.view.EdgeRealizer;
33 import y.view.EditMode;
34 import y.view.GenericEdgePainter;
35 import y.view.GenericEdgeRealizer;
36 import y.view.GenericNodeRealizer;
37 import y.view.Graph2D;
38 import y.view.LineType;
39 import y.view.NodeRealizer;
40 import y.view.ShinyPlateNodePainter;
41 import y.view.NavigationMode;
42 import y.algo.Bfs;
43
44 import javax.swing.AbstractAction;
45 import javax.swing.Action;
46 import javax.swing.JComboBox;
47 import javax.swing.JFileChooser;
48 import javax.swing.JToolBar;
49 import javax.swing.ScrollPaneConstants;
50 import javax.swing.filechooser.FileFilter;
51 import java.awt.BasicStroke;
52 import java.awt.Color;
53 import java.awt.Graphics2D;
54 import java.awt.Stroke;
55 import java.awt.Cursor;
56 import java.awt.event.ActionEvent;
57 import java.awt.event.ActionListener;
58 import java.awt.geom.GeneralPath;
59 import java.awt.geom.PathIterator;
60 import java.io.File;
61 import java.io.FilenameFilter;
62 import java.io.IOException;
63 import java.util.Map;
64 import java.net.URL;
65
66
67
115
116 public class FamilyTreeDemo extends DemoBase {
117
118
121 public static void main(String args[])
122 {
123 initLnF();
124
125 FamilyTreeDemo ftd = new FamilyTreeDemo();
126 ftd.start("Family Tree Demo");
127 }
128
129
134 protected EditMode createEditMode() {
135 EditMode editMode = new EditMode() {
136 protected void nodeClicked(Node v) {
137 moveToCenter(v);
138 }
139 };
140 editMode.allowEdgeCreation(false);
141 editMode.allowNodeCreation(false);
142 editMode.allowMoveLabels(false);
143 editMode.allowBendCreation(false);
144 editMode.allowMoveSelection(false);
145 editMode.allowMoving(true);
146 return editMode;
147 }
148
149 private GraphHider graphHider;
150
151
152
156 private void moveToCenter(final Node newCenter) {
157
158 graphHider.unhideAll();
160 NodeList toHide = new NodeList( view.getGraph2D().nodes() );
162 NodeMap nodeMap = view.getGraph2D().createNodeMap();
163 NodeList[] layers = Bfs.getLayers( view.getGraph2D(), new NodeList( newCenter ), false, nodeMap, 5 );
167 view.getGraph2D().disposeNodeMap( nodeMap );
168 for ( int i = 0; i < layers.length; i++ ) {
170 NodeList layer = layers[ i ];
171 toHide.removeAll( layer );
172 }
173
174 graphHider.hide( toHide );
176
177 getLayoutModule().mainrun();
179 view.fitContent();
181 }
182
183
186 protected class ShowAllAction extends AbstractAction {
187
188
189 public ShowAllAction() {
190 super("Show all");
191 }
192
193
197 public void actionPerformed(ActionEvent e) {
198 if (graphHider != null) {
199 graphHider.unhideAll();
200 }
201 getLayoutModule().mainrun();
202 view.fitContent();
203 }
204
205
206
215
216 }
217
218
219
220
223 protected JToolBar createToolBar() {
224 JToolBar jToolBar = super.createToolBar();
225 jToolBar.addSeparator();
226 jToolBar.add(new LayoutAction());
227 JComboBox jcb = createExampleComboBox();
229 if (jcb != null) {
230 jToolBar.add(jcb);
231 }
232 jToolBar.add(new ShowAllAction());
233 return jToolBar;
234 }
235
236
240 private JComboBox createExampleComboBox() {
241 String fqResourceName = FamilyTreeDemo.class.getPackage().getName().replace( '.', '/' ) + "/samples/KENNEDY.GED";
242
243
244 URL resource = getClass().getResource("samples/KENNEDY.GED");
245 if (resource == null) {
246 D.showError("Cannot load example files: missing resource " + fqResourceName + "\n" +
247 "Please ensure that your IDE recognizes \"*.ged\" files as resource files. \n" +
248 "Meanwhile you can load the sample files via the \"File/Load\" menu from the source folder of your distribution.");
249 return null;
250 }
251 String name = resource.getFile();
252 final String dirName = name.substring(0, name.lastIndexOf('/'));
253
254 final String[] dir = new File(dirName).list(new FilenameFilter(){
255 public boolean accept( File d, String s ) {
256 return s.toLowerCase().endsWith( ".ged" );
257 } } );
258 if (dir == null) {
259 D.showError("Cannot load example files: "+ dirName +" not found");
260 return null;
261 }
262 String[] combo = new String[dir.length + 1];
263 System.arraycopy(dir, 0, combo, 1, dir.length);
264 combo[0] = "Examples";
265 final JComboBox jcb = new JComboBox(combo);
266 jcb.addActionListener(new ActionListener() {
267 public void actionPerformed( ActionEvent e) {
268 String fileName = (String)jcb.getSelectedItem();
269 if (!"Examples".equals(fileName)) {
270 loadGedcom(dirName + System.getProperty("file.separator") + fileName);
271 }
272 }
273 });
274 return jcb;
275 }
276
277
281 private void loadGedcom(String name) {
282
283 Cursor oldCursor = view.getViewCursor();
284 view.setViewCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
285
286 final Graph2D graph = view.getGraph2D();
287 if (graphHider != null) {
288 graphHider.unhideAll();
289 }
290 graph.clear();
291 GedcomHandler gh = new GedcomHandler();
300 GMLIOHandler delegate = new GMLIOHandler();
301 gh.setReaderDelegate(delegate);
303 try {
304 gh.read(graph, name);
305 } catch (IOException e1) {
306 D.show(e1);
307 }
308
309 DataProvider dpType = null;
311 if(graph.getDataProvider(FamilyTreeLayouter.DP_KEY_FAMILY_TYPE) == null) {
312
313 dpType = new DataProviderAdapter() {
314 public Object get(Object o) {
315 NodeRealizer nr = graph.getRealizer((Node)o);
316 Color nodeColor = nr.getFillColor();
317 if (nodeColor != null && nodeColor.getRGB() == 0xFFCCCCFF) {
318 return FamilyTreeLayouter.TYPE_MALE;
319 }
320 if (nodeColor != null && nodeColor.getRGB() == 0xFFFF99CC) {
321 return FamilyTreeLayouter.TYPE_FEMALE;
322 }
323 if (nodeColor != null && nodeColor.getRGB() == 0xFF000000) {
324 return FamilyTreeLayouter.TYPE_FAMILY;
325 }
326 return null;
327 }
328 };
329 graph.addDataProvider(FamilyTreeLayouter.DP_KEY_FAMILY_TYPE, dpType);
330 }
331
332
334
341 try {
342 getLayoutModule().mainrun();
343 } catch (Exception e1) {
344 D.show(e1);
345 }
346
347
349 view.fitContent();
350 graph.updateViews();
351 view.setViewCursor(oldCursor);
352 }
353
354
355
360 protected Action createLoadAction() {
361 return new ImportAction();
362 }
363
364
365
366
367
368
369
372 protected class ImportAction extends AbstractAction {
373 JFileChooser chooser;
374
375 public ImportAction() {
376 super( "Load..." );
377 chooser = null;
378 }
379
380 public void actionPerformed( ActionEvent e ) {
381 if ( chooser == null ) {
382 chooser = new JFileChooser();
383 chooser.setFileFilter(new FileFilter() {
384 public boolean accept(File f) {
385 return f.isDirectory() || f.getName().toLowerCase().endsWith(".ged");
386 }
387 public String getDescription() {
388 return "Gedcom files";
389 }
390 });
391 }
392
393 if ( chooser.showOpenDialog( contentPane ) == JFileChooser.APPROVE_OPTION ) {
394 loadGedcom(chooser.getSelectedFile().toString());
395 }
396 }
397
398
399 }
400
401 private FamilyTreeLayoutModule getLayoutModule() {
402 if (ftlm == null) {
403 ftlm = new FamilyTreeLayoutModule();
404 ftlm.setGraph2D(view.getGraph2D());
405 }
406 return ftlm;
407 }
408
409 private FamilyTreeLayoutModule ftlm;
410
411
412
415 protected class LayoutAction extends AbstractAction {
416
417
418 public LayoutAction() {
419 super("Layout");
420 }
421
422
426 public void actionPerformed(ActionEvent e) {
427 if (getLayoutModule().getOptionHandler().showEditor()) {
428 Cursor oldCursor = view.getViewCursor();
429 view.setViewCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
430
431 getLayoutModule().mainrun();
432 view.setViewCursor(oldCursor);
433 }
434
435 }
436
437
438
447
448 }
449
450
454 protected class ExportAction extends AbstractAction {
455
456 private JFileChooser chooser;
457
458 public ExportAction() {
459 super("Export");
460 }
461
462
465 public void actionPerformed(ActionEvent e) {
466
467 if (chooser == null) {
468 chooser = new JFileChooser();
469 chooser.setFileFilter(new FileFilter() {
470 public boolean accept(File f) {
471 return f.isDirectory()
472 || f.getName().toLowerCase().endsWith(".ged");
473 }
474
475 public String getDescription() {
476 return "Gedcom files";
477 }
478 });
479 }
480 if (chooser.showOpenDialog(contentPane) == JFileChooser.APPROVE_OPTION) {
481 String name = chooser.getSelectedFile().toString();
482 if (!name.toLowerCase().endsWith(".ged")) {
483 name = name + ".ged";
484 }
485
486 GedcomHandler gh = new GedcomHandler();
487 final Graph2D graph = view.getGraph2D();
488
489 try {
491 gh.write(graph, name);
492 } catch (IOException e1) {
493 D.show(e1);
494 }
495 }
496 }
497
498 }
499
500
502
505 protected void initialize() {
506
507 GenericNodeRealizer.Factory factory = GenericNodeRealizer.getFactory();
509 Map implementationsMap = factory.createDefaultConfigurationMap();
510 ShinyPlateNodePainter spnp = new ShinyPlateNodePainter();
511 spnp.setDrawShadow(true);
512 implementationsMap.put(GenericNodeRealizer.Painter.class, spnp);
513 factory.addConfiguration("Individual", implementationsMap);
514
515 implementationsMap = factory.createDefaultConfigurationMap();
517 BevelNodePainter painter = new BevelNodePainter();
518 painter.setRadius(10);
519 painter.setDrawShadow(true);
520 implementationsMap.put(GenericNodeRealizer.Painter.class, painter);
521 factory.addConfiguration("Family", implementationsMap);
522
523 GenericEdgeRealizer.Factory edgeFactory = GenericEdgeRealizer.getFactory();
525 implementationsMap = edgeFactory.createDefaultConfigurationMap();
526 implementationsMap.put(GenericEdgeRealizer.Painter.class, new CustomEdgePainter());
527 edgeFactory.addConfiguration("Edge", implementationsMap);
528 GenericEdgeRealizer ger = new GenericEdgeRealizer();
529 ger.setConfiguration("Edge");
530 ger.setLineColor(new Color(0x808080));
531 ger.setLineType(LineType.LINE_2);
532 view.getGraph2D().setDefaultEdgeRealizer(ger);
533
534 BridgeCalculator bc = new BridgeCalculator();
536 bc.setCrossingStyle(BridgeCalculator.CROSSING_STYLE_GAP);
537 bc.setCrossingMode(BridgeCalculator.CROSSING_MODE_ORDER_INDUCED);
538 ((DefaultGraph2DRenderer) view.getGraph2DRenderer()).setBridgeCalculator(bc);
539
540 graphHider = new GraphHider(view.getGraph2D());
541
542
543 }
544
545
546
550 static final class CustomEdgePainter extends GenericEdgePainter {
551
552 protected GeneralPath adjustPath(EdgeRealizer context, BendList bends, GeneralPath path,
553 BridgeCalculator bridgeCalculator,
554 boolean selected) {
555 if (bridgeCalculator != null) {
556 GeneralPath p = new GeneralPath();
557 try {
558 PathIterator pathIterator = bridgeCalculator.insertBridges(path.getPathIterator(null, 1.0d));
559 p.append(pathIterator, true);
560 return super.adjustPath(context, bends, p, bridgeCalculator, selected);
561 } finally {
562 }
563 } else {
564 return super.adjustPath(context, bends, path, bridgeCalculator, selected);
565 }
566
567
568 }
569
570
571
572 protected void paintPath(EdgeRealizer context, BendList bends, GeneralPath path, Graphics2D gfx, boolean selected) {
573 Stroke s = gfx.getStroke();
574 Color oldColor = gfx.getColor();
575 if (s instanceof BasicStroke){
576 Color c;
577 if (!context.isSelected()){
578 initializeLine(context, gfx, selected);
579 c = gfx.getColor();
580 gfx.setColor(new Color(128,128,128,40));
581 gfx.translate(4, 4);
582 gfx.draw(path);
583 gfx.translate(-4, -4);
584 } else {
585 initializeSelectionLine(context, gfx, selected);
586 c = gfx.getColor();
587 }
588 Color newC = context.isSelected() ? Color.red :c;
589 gfx.setColor(new Color(128 + newC.getRed()/ 2, 128 + newC.getGreen()/ 2,128 + newC.getBlue()/ 2));
590 gfx.translate(-1, -1);
591 gfx.draw(path);
592 gfx.setColor(new Color(newC.getRed()/ 2, newC.getGreen()/ 2,newC.getBlue()/ 2));
593 gfx.translate(2, 2);
594 gfx.draw(path);
595 gfx.translate(-1, -1);
596 gfx.setColor(c);
597 gfx.draw(path);
598 gfx.setColor(oldColor);
599 } else {
600 gfx.draw(path);
601 }
602 }
603 }
604
605
606 }
607