001 /*
002 * Copyright 2007 Jeffrey Palm.
003 */
004
005 import java.awt.*;
006 import java.awt.event.*;
007 import java.io.*;
008 import java.util.*;
009 import java.util.List;
010 import javax.swing.*;
011 import javax.swing.event.*;
012 import javax.swing.table.*;
013
014 class MainFrame extends JFrame {
015
016 private SortableTableExample t;
017 private final tables del;
018
019 MainFrame(tables del) {
020 super(Constants.TITLE);
021 this.del = del;
022
023 JToolBar tb = new JToolBar();
024 tb.add(new JButton(new AbstractAction("Quit") {
025 public void actionPerformed(ActionEvent e) {
026 System.exit(0);
027 }
028 }));
029 tb.add(new JButton(new AbstractAction("Open") {
030 public void actionPerformed(ActionEvent e) {
031 try {
032 JFileChooser fc = new JFileChooser();
033 int res = fc.showOpenDialog(MainFrame.this);
034 if (res != JFileChooser.APPROVE_OPTION) return;
035 File sel = fc.getSelectedFile();
036 Util.log(this,"have file: " + sel);
037 } catch (Exception ee) {ee.printStackTrace();}
038 }
039 }));
040 tb.add(new JButton(new AbstractAction("Paste") {
041 public void actionPerformed(ActionEvent e) {
042 try {
043 final PasteFrame[] pfs = new PasteFrame[1];
044 PasteFrame pf = new PasteFrame(new Runnable() {
045 public void run() {
046 String s = pfs[0].getInnerText();
047 Finder f = createFinder(s);
048 if (f != null) find(f);
049 }
050 });
051 pfs[0] = pf;
052 pf.pack();
053 CenterHelper.center(pf);
054 pf.setVisible(true);
055 } catch (Exception ee) {ee.printStackTrace();}
056 }
057 }));
058 tb.add(new JButton(new AbstractAction("Output") {
059 public void actionPerformed(ActionEvent e) {
060 try {
061
062 } catch (Exception ee) {ee.printStackTrace();}
063 }
064 }));
065
066 add(tb,BorderLayout.NORTH);
067
068 this.t = new SortableTableExample();
069 getContentPane().add(t, BorderLayout.CENTER);
070 setSize(900,600);
071 setPreferredSize(new Dimension(900,600));
072
073 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
074
075 }
076
077 /**
078 * Decide what kind of finder to use for the plain text passed in.
079 * @param s plain text -- maybe CSV
080 */
081 private Finder createFinder(String s) {
082 //
083 // This is going to be be stupid But we'll look at all the lines
084 // and use the delimeter that shows up the same number of times on
085 // each line
086 //
087 char[] delims = {'\t',',',':'};
088 String delimStr = null;
089 outer: for (int i=0; i<delims.length; i++) {
090 char delim = delims[i];
091 BufferedReader in = null;
092 try {
093 in = new BufferedReader(new InputStreamReader(new StringInputStream(s)));
094 String line;
095 int num = -1;
096 int cnt = 0;
097 inner: while ((line = in.readLine()) != null) {
098 cnt = 0;
099 for (int j=0; j<line.length(); j++) {
100 if (line.charAt(j) == delim) cnt++;
101 }
102 System.out.println(delim + " " + num + ":" + cnt);
103 if (num == -1) { // first time
104 num = cnt;
105 } else if (cnt > 0) {
106 if (num != cnt) break inner;
107 }
108 }
109 String nextLine = in.readLine();
110 //
111 // If we're here we have a delim to use
112 //
113 if (nextLine != null && (num <= 0 || cnt != num)) continue;
114 delimStr = String.valueOf(delim);
115 break outer;
116 } catch (Exception e) {
117 Util.handle(this,e);
118 } finally {
119 try {if (in != null) in.close();} catch (Exception ee) {Util.handle(this,ee);}
120 }
121 }
122 Util.log(this,"delim "+delimStr);
123 if (delimStr != null) {
124 Util.log(this,"have a finder");
125 return new DelimFinder(delimStr,s);
126 }
127 return null;
128 }
129
130 private boolean running = false;
131
132 private void find(final Finder finder) {
133
134 // only run one at a time
135 if (running) return;
136
137 try {
138 new Thread(new Runnable() {
139 public void run() {
140 running = true;
141 try {
142 findInternal(finder);
143 } catch (Exception e) {
144 e.printStackTrace();
145 } finally {
146 running = false;
147 }
148 }
149 }).start();
150 } catch (Exception e) {e.printStackTrace();}
151 }
152
153 private void findInternal(Finder finder) throws Exception {
154
155 final P p = new P();
156
157 final boolean going[] = new boolean[]{true};
158
159 JFrame info = new JFrame();
160 info.getContentPane().add(p);
161 info.addWindowListener(new WindowAdapter() {
162 public void windowClosing(WindowEvent e) {
163 going[0] = false;
164 }
165 });
166 info.pack();
167 CenterHelper.center(info);
168 info.setVisible(true);
169
170
171 p.setMax(finder.getWork());
172
173 int i = 0;
174 int total = 0;
175
176
177 t.removeAllRows();
178
179 boolean first = true;
180 while (finder.hasNext()) {
181 List ress = finder.next(p);
182 for (Iterator jt = ress.iterator(); jt.hasNext();) {
183 List res = (List)jt.next();
184 if (res == null) continue;
185 Object[] data = res.toArray();
186 if (first) {
187 String[] headerStr = new String[data.length];
188 for (int j=0; j<headerStr.length; j++) headerStr[j] = "";
189 t.setHeader(headerStr);
190 first = false;
191 }
192 t.addRow(data);
193 t.repaint();
194 }
195 if (!going[0]) break;
196 }
197 t.repaint();
198
199 info.setVisible(false);
200 info.dispose();
201
202 }
203 //
204 // http://www.java2s.com/Code/Java/Swing-Components/SortableTableExample.htm
205 //
206 /**
207 * @version 1.0 02/25/99
208 */
209 class SortableTableExample extends JPanel {
210
211 void removeAllRows() {
212 while (dm.getRowCount() > 0) dm.removeRow(0);
213 }
214
215
216 void addRow(Object[] row) {
217 dm.addRow(row);
218 }
219
220 final SortableTableModel dm;
221 final JTable table;
222
223 SortableTableExample() {
224 this(new String[]{ });
225 }
226
227 void setHeader(String[] headerStr) {
228 int[] columnWidth = new int[headerStr.length];
229 for (int i=0; i<columnWidth.length; i++) columnWidth[i] = 150;
230 dm.setColumnIdentifiers(headerStr);
231 SortButtonRenderer renderer = new SortButtonRenderer();
232 TableColumnModel model = table.getColumnModel();
233 int n = headerStr.length;
234 for (int i = 0; i < n; i++) {
235 model.getColumn(i).setHeaderRenderer(renderer);
236 model.getColumn(i).setPreferredWidth(columnWidth[i]);
237 }
238
239 JTableHeader header = table.getTableHeader();
240 header.addMouseListener(new HeaderListener(header, renderer));
241 }
242
243 public SortableTableExample(String[] headerStr) {
244 setLayout(new BorderLayout());
245
246 dm = new SortableTableModel() {
247 public Class getColumnClass(int col) {
248 return String.class;
249 }
250
251 public boolean isCellEditable(int row, int col) {
252 return false;
253 }
254
255 };
256
257 table = new JTable(dm);
258
259 table.setShowGrid(false);
260 table.setShowVerticalLines(true);
261 table.setShowHorizontalLines(false);
262 table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
263 table.setColumnSelectionAllowed(true);
264
265 class Lis implements MouseListener,KeyListener {
266
267 private int keyDown = -1;
268
269 // MouseListener
270 public void mouseClicked(MouseEvent e) {}
271 public void mousePressed(MouseEvent e) {
272 if (keyDown != KeyEvent.VK_CONTROL) return;
273 //
274 // Show a menu of all the things we can do
275 //
276 showMenu();
277 }
278 public void mouseReleased(MouseEvent e) {}
279 public void mouseEntered(MouseEvent e) {}
280 public void mouseExited(MouseEvent e) {}
281
282 // KeyListener
283 public void keyTyped(KeyEvent e) {}
284 public void keyPressed(KeyEvent e) {keyDown = e.getKeyCode();}
285 public void keyReleased(KeyEvent e) {keyDown = -1;}
286
287 }
288 Lis lis = new Lis();
289 table.addMouseListener(lis);
290 table.addKeyListener(lis);
291
292 setHeader(headerStr);
293
294 JScrollPane pane = new JScrollPane(table);
295 add(pane, BorderLayout.CENTER);
296 }
297
298 private void showMenu() {
299 Util.log(this,"Showing menu");
300 //
301 // Collect all the selected values
302 // TODO: This sucks
303 List sel = new ArrayList();
304 for (int i=0, I=table.getRowCount(); i<I; i++) {
305 for (int j=0, J=table.getColumnCount(); j<J; j++) {
306 if (table.isCellSelected(i,j)) sel.add(table.getValueAt(i,j));
307 }
308 }
309 //
310 // Represent the actions we can do
311 //
312 List folds = del.getFolds();
313 Collections.sort(folds, new Comparator() {
314 public int compare(Object o1, Object o2) {
315 return ((Fold)o1).name().compareTo(((Fold)o2).name());
316 }
317 });
318 Fold selFold = (Fold)JOptionPane.showInputDialog(this,"Select a function","Select a function",
319 JOptionPane.INFORMATION_MESSAGE,
320 null,folds.toArray(),folds.get(0));
321 if (selFold != null) {
322 Object res = selFold.fold(sel);
323 JPanel p = Util.xp();
324 p.add(new JLabel("The " + selFold.name() + " is "));
325 JTextField txt = new JTextField(String.valueOf(res));
326 p.add(txt);
327 Util.showMsg(p);
328 }
329 }
330
331 class HeaderListener extends MouseAdapter {
332 JTableHeader header;
333
334 SortButtonRenderer renderer;
335
336 HeaderListener(JTableHeader header, SortButtonRenderer renderer) {
337 this.header = header;
338 this.renderer = renderer;
339 }
340
341 public void mousePressed(MouseEvent e) {
342 int col = header.columnAtPoint(e.getPoint());
343 int sortCol = header.getTable().convertColumnIndexToModel(col);
344 renderer.setPressedColumn(col);
345 renderer.setSelectedColumn(col);
346 header.repaint();
347
348 if (header.getTable().isEditing()) {
349 header.getTable().getCellEditor().stopCellEditing();
350 }
351
352 boolean isAscent;
353 if (SortButtonRenderer.DOWN == renderer.getState(col)) {
354 isAscent = true;
355 } else {
356 isAscent = false;
357 }
358 ((SortableTableModel) header.getTable().getModel()).sortByColumn(sortCol, isAscent);
359 }
360
361 public void mouseReleased(MouseEvent e) {
362 int col = header.columnAtPoint(e.getPoint());
363 renderer.setPressedColumn(-1); // clear
364 header.repaint();
365 }
366 }
367
368 }
369
370 static class SortableTableModel extends DefaultTableModel {
371
372 int[] indexes;
373
374 TableSorter sorter;
375
376 public SortableTableModel() {
377 }
378
379 public Object getValueAt(int row, int col) {
380 int rowIndex = row;
381 if (indexes != null) {
382 rowIndex = indexes[row];
383 }
384 return super.getValueAt(rowIndex, col);
385 }
386
387 public void setValueAt(Object value, int row, int col) {
388 int rowIndex = row;
389 if (indexes != null) {
390 rowIndex = indexes[row];
391 }
392 super.setValueAt(value, rowIndex, col);
393 }
394
395 public void sortByColumn(int column, boolean isAscent) {
396 if (sorter == null) {
397 sorter = new TableSorter(this);
398 }
399 sorter.sort(column, isAscent);
400 fireTableDataChanged();
401 }
402
403 public int[] getIndexes() {
404 int n = getRowCount();
405 if (indexes != null) {
406 if (indexes.length == n) {
407 return indexes;
408 }
409 }
410 indexes = new int[n];
411 for (int i = 0; i < n; i++) {
412 indexes[i] = i;
413 }
414 return indexes;
415 }
416 }
417
418 static class TableSorter {
419 SortableTableModel model;
420
421 public TableSorter(SortableTableModel model) {
422 this.model = model;
423 }
424
425 //n2 selection
426 public void sort(int column, boolean isAscent) {
427 int n = model.getRowCount();
428 int[] indexes = model.getIndexes();
429
430 for (int i = 0; i < n - 1; i++) {
431 int k = i;
432 for (int j = i + 1; j < n; j++) {
433 if (isAscent) {
434 if (compare(column, j, k) < 0) {
435 k = j;
436 }
437 } else {
438 if (compare(column, j, k) > 0) {
439 k = j;
440 }
441 }
442 }
443 int tmp = indexes[i];
444 indexes[i] = indexes[k];
445 indexes[k] = tmp;
446 }
447 }
448
449 // comparaters
450
451 public int compare(int column, int row1, int row2) {
452 Object o1 = model.getValueAt(row1, column);
453 Object o2 = model.getValueAt(row2, column);
454 if (o1 == null && o2 == null) {
455 return 0;
456 } else if (o1 == null) {
457 return -1;
458 } else if (o2 == null) {
459 return 1;
460 } else {
461 Class type = model.getColumnClass(column);
462 if (type.getSuperclass() == Number.class) {
463 return compare((Number) o1, (Number) o2);
464 } else if (type == String.class) {
465 return ((String) o1).compareTo((String) o2);
466 } else if (type == Date.class) {
467 return compare((Date) o1, (Date) o2);
468 } else if (type == Boolean.class) {
469 return compare((Boolean) o1, (Boolean) o2);
470 } else {
471 return ((String) o1).compareTo((String) o2);
472 }
473 }
474 }
475
476 public int compare(Number o1, Number o2) {
477 double n1 = o1.doubleValue();
478 double n2 = o2.doubleValue();
479 if (n1 < n2) {
480 return -1;
481 } else if (n1 > n2) {
482 return 1;
483 } else {
484 return 0;
485 }
486 }
487
488 public int compare(Date o1, Date o2) {
489 long n1 = o1.getTime();
490 long n2 = o2.getTime();
491 if (n1 < n2) {
492 return -1;
493 } else if (n1 > n2) {
494 return 1;
495 } else {
496 return 0;
497 }
498 }
499
500 public int compare(Boolean o1, Boolean o2) {
501 boolean b1 = o1.booleanValue();
502 boolean b2 = o2.booleanValue();
503 if (b1 == b2) {
504 return 0;
505 } else if (b1) {
506 return 1;
507 } else {
508 return -1;
509 }
510 }
511
512 }
513
514 static class SortButtonRenderer extends JButton implements TableCellRenderer {
515 public static final int NONE = 0;
516
517 public static final int DOWN = 1;
518
519 public static final int UP = 2;
520
521 int pushedColumn;
522
523 Hashtable state;
524
525 JButton downButton, upButton;
526
527 public SortButtonRenderer() {
528 pushedColumn = -1;
529 state = new Hashtable();
530
531 setMargin(new Insets(0, 0, 0, 0));
532 setHorizontalTextPosition(LEFT);
533 setIcon(new BlankIcon());
534
535 downButton = new JButton();
536 downButton.setMargin(new Insets(0, 0, 0, 0));
537 downButton.setHorizontalTextPosition(LEFT);
538 downButton
539 .setIcon(new BevelArrowIcon(BevelArrowIcon.DOWN, false, false));
540 downButton.setPressedIcon(new BevelArrowIcon(BevelArrowIcon.DOWN,
541 false, true));
542
543 upButton = new JButton();
544 upButton.setMargin(new Insets(0, 0, 0, 0));
545 upButton.setHorizontalTextPosition(LEFT);
546 upButton.setIcon(new BevelArrowIcon(BevelArrowIcon.UP, false, false));
547 upButton.setPressedIcon(new BevelArrowIcon(BevelArrowIcon.UP, false,
548 true));
549
550 }
551
552 public Component getTableCellRendererComponent(JTable table, Object value,
553 boolean isSelected, boolean hasFocus,
554 int row, int column) {
555 JButton button = this;
556 Object obj = state.get(new Integer(column));
557 if (obj != null) {
558 if (((Integer) obj).intValue() == DOWN) {
559 button = downButton;
560 } else {
561 button = upButton;
562 }
563 }
564 button.setText((value == null) ? "" : value.toString());
565 boolean isPressed = (column == pushedColumn);
566 button.getModel().setPressed(isPressed);
567 button.getModel().setArmed(isPressed);
568 return button;
569 }
570
571 public void setPressedColumn(int col) {
572 pushedColumn = col;
573 }
574
575 public void setSelectedColumn(int col) {
576 if (col < 0)
577 return;
578 Integer value = null;
579 Object obj = state.get(new Integer(col));
580 if (obj == null) {
581 value = new Integer(DOWN);
582 } else {
583 if (((Integer) obj).intValue() == DOWN) {
584 value = new Integer(UP);
585 } else {
586 value = new Integer(DOWN);
587 }
588 }
589 state.clear();
590 state.put(new Integer(col), value);
591 }
592
593 public int getState(int col) {
594 int retValue;
595 Object obj = state.get(new Integer(col));
596 if (obj == null) {
597 retValue = NONE;
598 } else {
599 if (((Integer) obj).intValue() == DOWN) {
600 retValue = DOWN;
601 } else {
602 retValue = UP;
603 }
604 }
605 return retValue;
606 }
607 }
608
609 static class BevelArrowIcon implements Icon {
610 public static final int UP = 0; // direction
611
612 public static final int DOWN = 1;
613
614 private static final int DEFAULT_SIZE = 11;
615
616 private Color edge1;
617
618 private Color edge2;
619
620 private Color fill;
621
622 private int size;
623
624 private int direction;
625
626 public BevelArrowIcon(int direction, boolean isRaisedView,
627 boolean isPressedView) {
628 if (isRaisedView) {
629 if (isPressedView) {
630 init(UIManager.getColor("controlLtHighlight"), UIManager
631 .getColor("controlDkShadow"), UIManager
632 .getColor("controlShadow"), DEFAULT_SIZE, direction);
633 } else {
634 init(UIManager.getColor("controlHighlight"), UIManager
635 .getColor("controlShadow"), UIManager
636 .getColor("control"), DEFAULT_SIZE, direction);
637 }
638 } else {
639 if (isPressedView) {
640 init(UIManager.getColor("controlDkShadow"), UIManager
641 .getColor("controlLtHighlight"), UIManager
642 .getColor("controlShadow"), DEFAULT_SIZE, direction);
643 } else {
644 init(UIManager.getColor("controlShadow"), UIManager
645 .getColor("controlHighlight"), UIManager
646 .getColor("control"), DEFAULT_SIZE, direction);
647 }
648 }
649 }
650
651 public BevelArrowIcon(Color edge1, Color edge2, Color fill, int size,
652 int direction) {
653 init(edge1, edge2, fill, size, direction);
654 }
655
656 public void paintIcon(Component c, Graphics g, int x, int y) {
657 switch (direction) {
658 case DOWN:
659 drawDownArrow(g, x, y);
660 break;
661 case UP:
662 drawUpArrow(g, x, y);
663 break;
664 }
665 }
666
667 public int getIconWidth() {
668 return size;
669 }
670
671 public int getIconHeight() {
672 return size;
673 }
674
675 private void init(Color edge1, Color edge2, Color fill, int size,
676 int direction) {
677 this.edge1 = edge1;
678 this.edge2 = edge2;
679 this.fill = fill;
680 this.size = size;
681 this.direction = direction;
682 }
683
684 private void drawDownArrow(Graphics g, int xo, int yo) {
685 g.setColor(edge1);
686 g.drawLine(xo, yo, xo + size - 1, yo);
687 g.drawLine(xo, yo + 1, xo + size - 3, yo + 1);
688 g.setColor(edge2);
689 g.drawLine(xo + size - 2, yo + 1, xo + size - 1, yo + 1);
690 int x = xo + 1;
691 int y = yo + 2;
692 int dx = size - 6;
693 while (y + 1 < yo + size) {
694 g.setColor(edge1);
695 g.drawLine(x, y, x + 1, y);
696 g.drawLine(x, y + 1, x + 1, y + 1);
697 if (0 < dx) {
698 g.setColor(fill);
699 g.drawLine(x + 2, y, x + 1 + dx, y);
700 g.drawLine(x + 2, y + 1, x + 1 + dx, y + 1);
701 }
702 g.setColor(edge2);
703 g.drawLine(x + dx + 2, y, x + dx + 3, y);
704 g.drawLine(x + dx + 2, y + 1, x + dx + 3, y + 1);
705 x += 1;
706 y += 2;
707 dx -= 2;
708 }
709 g.setColor(edge1);
710 g.drawLine(xo + (size / 2), yo + size - 1, xo + (size / 2), yo + size
711 - 1);
712 }
713
714 private void drawUpArrow(Graphics g, int xo, int yo) {
715 g.setColor(edge1);
716 int x = xo + (size / 2);
717 g.drawLine(x, yo, x, yo);
718 x--;
719 int y = yo + 1;
720 int dx = 0;
721 while (y + 3 < yo + size) {
722 g.setColor(edge1);
723 g.drawLine(x, y, x + 1, y);
724 g.drawLine(x, y + 1, x + 1, y + 1);
725 if (0 < dx) {
726 g.setColor(fill);
727 g.drawLine(x + 2, y, x + 1 + dx, y);
728 g.drawLine(x + 2, y + 1, x + 1 + dx, y + 1);
729 }
730 g.setColor(edge2);
731 g.drawLine(x + dx + 2, y, x + dx + 3, y);
732 g.drawLine(x + dx + 2, y + 1, x + dx + 3, y + 1);
733 x -= 1;
734 y += 2;
735 dx += 2;
736 }
737 g.setColor(edge1);
738 g.drawLine(xo, yo + size - 3, xo + 1, yo + size - 3);
739 g.setColor(edge2);
740 g.drawLine(xo + 2, yo + size - 2, xo + size - 1, yo + size - 2);
741 g.drawLine(xo, yo + size - 1, xo + size, yo + size - 1);
742 }
743
744 }
745
746 static class BlankIcon implements Icon {
747 private Color fillColor;
748
749 private int size;
750
751 public BlankIcon() {
752 this(null, 11);
753 }
754
755 public BlankIcon(Color color, int size) {
756 //UIManager.getColor("control")
757 //UIManager.getColor("controlShadow")
758 fillColor = color;
759
760 this.size = size;
761 }
762
763 public void paintIcon(Component c, Graphics g, int x, int y) {
764 if (fillColor != null) {
765 g.setColor(fillColor);
766 g.drawRect(x, y, size - 1, size - 1);
767 }
768 }
769
770 public int getIconWidth() {
771 return size;
772 }
773
774 public int getIconHeight() {
775 return size;
776 }
777 }
778
779
780 }