|
This is the listing of the GUI for BudgetPro. For a discussion, see Chapter 16. 1 package net.multitool.gui; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import javax.swing.*; 6 import javax.swing.event.*; 7 import javax.swing.table.*; 8 import java.util.*; 9 import net.multitool.core.*; 10 11 /** 12 * This class is the main application class for the BudgetPro gui 13 */ 14 15 public class 16 BudgetPro 17 { 18 Account top; 19 Account current; 20 21 // gui components 22 private JFrame frame; // needed by dialogs to root themselves 23 private JLabel nam; 24 private JLabel tot; 25 private JLabel val; 26 private JButton upton = new JButton( new ImageIcon("net/multitool/gui/back.gif")); 27 private JButton creat = new JButton("New Subaccount"); 28 private JButton view = new JButton("View Subaccount"); 29 private JButton clos = new JButton("Quit"); 30 31 private JTable list; 32 private AbstractTableModel model; 33 34 private AcctDialog askem; // make once, use often 35 36 // Set Up an Action for a Button 37 private ActionListener upAction = new ActionListener() 38 { 39 public void 40 actionPerformed(ActionEvent e) 41 { 42 // this is the action for UP arrow icon; 43 Account next; 44 next = current.getParent(); 45 if (next != null) { 46 current = next; 47 setStatus(); 48 // TODO: notify the table, too 49 model.fireTableDataChanged(); 50 } // TODO: else infodialog or Beep. 51 } 52 } ; 53 54 private ActionListener cdAction = new ActionListener() 55 { 56 public void 57 actionPerformed(ActionEvent e) 58 { 59 // this is the action for VIEW subdirectory; 60 // a "cd" into the subaccount. 61 int row = list.getSelectedRow(); 62 // System.out.println("Row="+row); // DEBUG; TODO: REMOVE 63 if (row > -1) { // only if a row was selected 64 String subname = (String) model.getValueAt(row, 0); // name column 65 Account next = current.getSub(subname); 66 if (next != null) { 67 current = next; 68 // System.out.println("cd to:"+current.getName()); 69 setStatus(); 70 // notify the table, too 71 model.fireTableDataChanged(); 72 } // TODO: else infodialog or Beep. 73 } 74 } 75 } ; 76 77 // TEST ONLY: 78 int testid = 0; 79 80 BudgetPro(JFrame frame, String username, String value) 81 { 82 this.frame = frame; 83 top = new Account("TopLevel", new User(username), value); 84 current = top; 85 86 } // constructor 87 88 private Component 89 createStatus() 90 { 91 JPanel retval = new JPanel(); // default: flow layout 92 93 upton.addActionListener(upAction); 94 95 nam = new JLabel("Account: Name"); 96 tot = new JLabel("Total: $"); 97 val = new JLabel("Remaining: $"); 98 99 retval.add(upton); 100 retval.add(nam); 101 retval.add(tot); 102 retval.add(val); 103 104 setStatus(); 105 106 return retval; 107 } // createStatus 108 109 /** 110 * Set the values of the status fields, 111 * as when the account has changed. 112 */ 113 private void 114 setStatus() 115 { 116 nam.setText("Account: "+current.getName()); 117 tot.setText("Total: $"+current.getTotal()); 118 // tot.setText("SubAccounts: "+current.size()); 119 val.setText("Remaining: $"+current.getBalance()); 120 121 // disable the button if there is no "up" to go 122 if (current.getParent() == null) { 123 upton.setEnabled(false); 124 } else { 125 upton.setEnabled(true); 126 } 127 128 } // setStatus 129 130 private Component 131 createList() 132 { 133 JScrollPane retval; 134 135 model = new AbstractTableModel() 136 { 137 private String [] columnNames = {"Account", "Owner", "Value"}; 138 139 public String 140 getColumnName(int col) { 141 return columnNames[col]; 142 } // getColumnName 143 144 public int 145 getRowCount() 146 { 147 int retval; 148 149 if (current != null) { 150 retval = current.size(); 151 } else { 152 retval = 1; // testing only 153 } 154 155 return retval; 156 157 } // getRowCount 158 159 public int getColumnCount() { return columnNames.length; } 160 161 public Object 162 getValueAt(int row, int col) { 163 Object retval = null; 164 Account aa = null; 165 // return "---"; // rowData[row][col]; 166 int count = 0; 167 for (Iterator itr=current.getAllSubs(); itr.hasNext(); ) 168 { 169 count++; 170 aa = (Account) itr.next(); 171 if (count > row) { break; } 172 } // next 173 switch (col) { 174 case 0: 175 retval = aa.getName(); 176 break; 177 case 1: 178 retval = aa.getOwner(); 179 break; 180 case 2: 181 retval = aa.getTotal(); 182 break; 183 } // endswitch 184 return retval; 185 } // getValueAt 186 187 public boolean 188 isCellEditable(int row, int col) 189 { 190 return false; 191 } // isCellEditable 192 }; 193 list = new JTable(model); 194 list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 195 196 list.getSelectionModel().addListSelectionListener( 197 new ListSelectionListener() 198 { 199 public void 200 valueChanged(ListSelectionEvent e) 201 { 202 ListSelectionModel lsm = (ListSelectionModel)e.getSource(); 203 if (lsm.isSelectionEmpty()) { 204 view.setEnabled(false); 205 } else { 206 view.setEnabled(true); 207 } 208 } // valueChanged 209 } 210 ); 211 212 retval = new JScrollPane(list); 213 214 return retval; 215 216 } // createList 217 218 private Component 219 createButtons(JRootPane root) 220 { 221 JPanel retval = new JPanel(); // default: flow layout 222 223 //Lay out the buttons from left to right. 224 retval.setLayout(new BoxLayout(retval, BoxLayout.X_AXIS)); 225 retval.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 226 retval.add(Box.createHorizontalGlue()); 227 retval.add(creat); 228 retval.add(Box.createRigidArea(new Dimension(10, 0))); 229 retval.add(view); 230 retval.add(Box.createRigidArea(new Dimension(10, 0))); 231 retval.add(clos); 232 233 // ---------------------------------------- Define some actions 234 ActionListener closAction = new ActionListener() 235 { 236 public void 237 actionPerformed(ActionEvent e) 238 { 239 System.exit(0); 240 } 241 } ; 242 clos.addActionListener(closAction); 243 244 ActionListener creatAction = new ActionListener() 245 { 246 public void 247 actionPerformed(ActionEvent e) 248 { 249 Account child; 250 // get the info via a Dialog (of sorts) 251 if (askem == null) { 252 askem = new AcctDialog(frame, "New Subaccount"); 253 } else { 254 askem.clear(); 255 askem.setVisible(true); 256 } 257 String subName = askem.getName(); 258 String subAmnt = askem.getAmnt(); 259 260 // if empty, assume the operation was cancelled, else: 261 if ((subName != null) && (subName.length() > 0)) { 262 child = current.createSub(subName, subAmnt); 263 setStatus(); 264 model.fireTableDataChanged(); // notify the table 265 } 266 } 267 }; 268 creat.addActionListener(creatAction); 269 270 // function is to get selection from table and cd there 271 view.addActionListener(cdAction); 272 // but it starts off disabled, since there is no data yet 273 view.setEnabled(false); 274 275 // ------------------------------------------------------------ 276 frame.getRootPane().setDefaultButton(creat); 277 clos.grabFocus(); 278 279 return retval; 280 281 } // createButtons 282 283 public static void 284 main(String[] args) 285 { 286 BudgetPro app = null; 287 288 //Create the top-level container 289 JFrame frame = new JFrame("BudgetPro"); 290 291 // ----------- set up the account/app based on the command line args 292 try { 293 String username = System.getProperty("user.name", "default"); 294 if (args.length > 0) { 295 app = new BudgetPro(frame, username, args[0]); 296 } else { 297 System.err.println("usage: BudgetPro dollar_amt"); 298 System.exit(1); 299 } 300 } catch (Exception e) { 301 System.err.println("Error on startup."); 302 e.printStackTrace(); 303 System.exit(2); 304 } 305 306 // ----------- now set up the UI and get things going 307 try { 308 UIManager.setLookAndFeel( 309 UIManager.getCrossPlatformLookAndFeelClassName()); 310 } catch (Exception e) { 311 System.err.println("Can't set the desired look and feel."); 312 e.printStackTrace(); 313 System.exit(3); 314 } 315 316 // build the pieces and add them to the top-level container 317 318 Component status = app.createStatus(); 319 frame.getContentPane().add(status, BorderLayout.NORTH); 320 321 Component list = app.createList(); 322 frame.getContentPane().add(list, BorderLayout.CENTER); 323 324 Component buttons = app.createButtons(frame.getRootPane()); 325 frame.getContentPane().add(buttons, BorderLayout.SOUTH); 326 327 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 328 frame.pack(); 329 frame.setVisible(true); 330 } // main 331 332 } // class BudgetPro Here is the code for the dialog for creating new accounts, AcctDialog.java: 1 package net.multitool.gui; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import javax.swing.*; 6 import javax.swing.table.*; 7 import java.util.*; 8 import net.multitool.core.*; 9 10 class 11 AcctDialog 12 extends JDialog 13 { 14 JDialog dialog; // for reference from the buttons' actions 15 JTextField nameField; 16 JTextField amntField; 17 18 AcctDialog(JFrame frame, String title) 19 { 20 super(frame, title, true); 21 dialog = this; 22 nameField = new JTextField(25); 23 amntField = new JTextField(9); 24 25 // right justify the numeric field 26 amntField.setHorizontalAlignment(JTextField.RIGHT); 27 28 // TODO: so that <Enter> will do a create 29 // this.getInputMap().put(KeyStroke.getKeyStroke("Enter"), "create"); 30 /* 31 Action myAction = new AbstractAction("doSomething") { 32 public void actionPerformed() { 33 doSomething(); 34 } 35 }; 36 myComponent.getActionMap().put(myAction.get(Action.NAME), myAction); 37 */ 38 39 //--------------------------------------------------Label on top---- 40 JLabel label = new JLabel("<html><p align=left><i>" 41 + "Enter the info to create a subaccount.<br>" 42 + "</i>"); 43 label.setHorizontalAlignment(JLabel.LEFT); 44 Font font = label.getFont(); 45 label.setFont(label.getFont().deriveFont(font.PLAIN, 14.0f)); 46 47 //--------------------------------------------------Text Fields---- 48 String[] labels = {"(Sub)Account Name: ", "Dollar Amount: "}; 49 JTextField [] fields = {nameField, amntField}; 50 int numPairs = fields.length; 51 52 //Create and populate the panel. 53 JPanel textes = new JPanel(new SpringLayout()); 54 for (int i = 0; i < numPairs; i++) { 55 JLabel l = new JLabel(labels[i], JLabel.TRAILING); 56 textes.add(l); 57 l.setLabelFor(fields[i]); // not nec. since we have no kb shortcuts 58 textes.add(fields[i]); 59 } 60 61 //Lay out the panel. 62 SpringUtilities.makeCompactGrid(textes, 63 numPairs, 2, //rows, cols 64 6, 6, //initX, initY 65 6, 6); //xPad, yPad 66 67 68 //--------------------------------------------------Buttons on bottom 69 JButton createButton = new JButton("Create"); 70 createButton.addActionListener(new ActionListener() { 71 public void actionPerformed(ActionEvent e) { 72 nameField.grabFocus(); // before leaving, ready for next time. 73 dialog.setVisible(false); // go away 74 } 75 }); 76 77 JButton cancelButton = new JButton("Cancel"); 78 cancelButton.addActionListener(new ActionListener() { 79 public void actionPerformed(ActionEvent e) { 80 clear(); // toss out any entry 81 dialog.setVisible(false); 82 } 83 }); 84 getRootPane().setDefaultButton(createButton); 85 86 JPanel closePanel = new JPanel(); 87 closePanel.setLayout(new BoxLayout(closePanel, BoxLayout.LINE_AXIS)); 88 closePanel.add(Box.createHorizontalGlue()); 89 closePanel.add(createButton); 90 closePanel.add(Box.createRigidArea(new Dimension(5, 0))); 91 closePanel.add(cancelButton); 92 closePanel.setBorder(BorderFactory.createEmptyBorder(10,0,5,5)); 93 94 JPanel contentPane = new JPanel(new BorderLayout()); 95 contentPane.add(label, BorderLayout.PAGE_START); 96 contentPane.add(textes, BorderLayout.CENTER); 97 contentPane.add(closePanel, BorderLayout.PAGE_END); 98 contentPane.setOpaque(true); 99 setContentPane(contentPane); 100 101 //Show it. 102 setSize(new Dimension(300, 160)); 103 setLocationRelativeTo(frame); 104 setVisible(true); 105 106 } // constructor 107 108 public String 109 getName() 110 { 111 String retval = null; 112 if (nameField != null) { 113 retval = nameField.getText(); 114 } 115 return retval; 116 } // getName 117 118 public String 119 getAmnt() 120 { 121 String retval = null; 122 if (amntField != null) { 123 retval = amntField.getText(); 124 } 125 return retval; 126 } // getAmnt 127 128 public void 129 clear() 130 { 131 nameField.setText(null); 132 amntField.setText(null); 133 } // clear 134 135 } // class AcctDialog |
|