001: /*
002: * ProfileEditorPanel.java
003: *
004: * This file is part of SQL Workbench/J, http://www.sql-workbench.net
005: *
006: * Copyright 2002-2008, Thomas Kellerer
007: * No part of this code maybe reused without the permission of the author
008: *
009: * To contact the author please send an email to: support@sql-workbench.net
010: *
011: */
012: package workbench.gui.profiles;
013:
014: import java.awt.BorderLayout;
015: import java.awt.Dialog;
016: import java.awt.Point;
017: import java.awt.event.MouseListener;
018: import java.util.List;
019: import javax.swing.DefaultComboBoxModel;
020: import javax.swing.JComboBox;
021: import javax.swing.JLabel;
022: import javax.swing.JPanel;
023: import javax.swing.JToolBar;
024: import javax.swing.SwingUtilities;
025: import javax.swing.event.TreeSelectionListener;
026: import javax.swing.tree.DefaultMutableTreeNode;
027: import javax.swing.tree.TreeNode;
028: import javax.swing.tree.TreePath;
029: import workbench.db.ConnectionMgr;
030: import workbench.db.ConnectionProfile;
031: import workbench.gui.WbSwingUtilities;
032: import workbench.gui.actions.CollapseTreeAction;
033: import workbench.gui.actions.CopyProfileAction;
034: import workbench.gui.actions.DeleteListEntryAction;
035: import workbench.gui.actions.ExpandTreeAction;
036: import workbench.gui.actions.NewListEntryAction;
037: import workbench.gui.actions.SaveListFileAction;
038: import workbench.gui.components.ValidatingDialog;
039: import workbench.gui.components.WbSplitPane;
040: import workbench.gui.components.WbToolbar;
041: import workbench.gui.components.WbTraversalPolicy;
042: import workbench.interfaces.FileActions;
043: import workbench.interfaces.ValidatingComponent;
044: import workbench.log.LogMgr;
045: import workbench.resource.ResourceMgr;
046: import workbench.resource.Settings;
047: import workbench.util.StringUtil;
048:
049: /**
050: *
051: * @author support@sql-workbench.net
052: */
053: public class ProfileEditorPanel extends JPanel implements FileActions,
054: ValidatingComponent {
055: private ProfileListModel model;
056: private JToolBar toolbar;
057: protected ConnectionEditorPanel connectionEditor;
058: private MouseListener listMouseListener;
059: private ProfileFilter filter;
060: private NewListEntryAction newItem;
061: private CopyProfileAction copyItem;
062: private DeleteListEntryAction deleteItem;
063: protected boolean dummyAdded;
064:
065: public ProfileEditorPanel(String lastProfileKey) {
066: initComponents(); // will initialize the model!
067:
068: this .connectionEditor = new ConnectionEditorPanel();
069: JPanel dummy = new JPanel(new BorderLayout());
070: dummy.add(connectionEditor, BorderLayout.CENTER);
071: this .jSplitPane.setRightComponent(dummy);
072: this .fillDrivers();
073:
074: JPanel p = new JPanel();
075: p.setLayout(new BorderLayout());
076: this .toolbar = new WbToolbar();
077: newItem = new NewListEntryAction(this , "LblNewProfile");
078: newItem.setIcon(ResourceMgr.getImage("NewProfile"));
079: this .toolbar.add(newItem);
080:
081: copyItem = new CopyProfileAction(this );
082: copyItem.setEnabled(false);
083: this .toolbar.add(copyItem);
084: ProfileTree tree = (ProfileTree) profileTree;
085: tree.setBorder(null);
086:
087: this .toolbar.add(new NewGroupAction(tree));
088:
089: this .toolbar.addSeparator();
090: deleteItem = new DeleteListEntryAction(this );
091: deleteItem.setEnabled(false);
092: this .toolbar.add(deleteItem);
093:
094: this .toolbar.addSeparator();
095: this .toolbar.add(new SaveListFileAction(this ));
096:
097: this .toolbar.addSeparator();
098: this .toolbar.add(new ExpandTreeAction(tree));
099: this .toolbar.add(new CollapseTreeAction(tree));
100:
101: this .listPanel.add(toolbar, BorderLayout.NORTH);
102:
103: tree.setDeleteAction(deleteItem);
104:
105: WbTraversalPolicy policy = new WbTraversalPolicy();
106: this .setFocusCycleRoot(false);
107: policy.addComponent(this .profileTree);
108: policy.addComponent(this .connectionEditor);
109: policy.setDefaultComponent(this .profileTree);
110: this .setFocusTraversalPolicy(policy);
111:
112: buildTree();
113: restoreSettings();
114:
115: final ProfileKey last = Settings.getInstance()
116: .getLastConnection(lastProfileKey);
117: ((ProfileTree) profileTree).selectProfile(last);
118: }
119:
120: public void done() {
121: if (this .filter != null) {
122: this .filter.done();
123: }
124: }
125:
126: public void setInitialFocus() {
127: if (dummyAdded) {
128: connectionEditor.setFocusToTitle();
129: } else {
130: profileTree.requestFocus();
131: }
132: }
133:
134: public void addSelectionListener(TreeSelectionListener listener) {
135: this .profileTree.addTreeSelectionListener(listener);
136: }
137:
138: private void fillDrivers() {
139: List drivers = ConnectionMgr.getInstance().getDrivers();
140: this .connectionEditor.setDrivers(drivers);
141: }
142:
143: public void restoreSettings() {
144: int pos = Settings.getInstance().getProfileDividerLocation();
145: if (pos < 210) {
146: pos = 210; // make sure the whole toolbar for the tree is visible!
147: }
148: this .jSplitPane.setDividerLocation(pos);
149: String groups = Settings.getInstance().getProperty(
150: "workbench.profiles.expandedgroups", null);
151: List l = StringUtil.stringToList(groups, ",", true, true);
152: ((ProfileTree) profileTree).expandGroups(l);
153: }
154:
155: public void saveSettings() {
156: Settings.getInstance().setProfileDividerLocation(
157: this .jSplitPane.getDividerLocation());
158: List expandedGroups = ((ProfileTree) profileTree)
159: .getExpandedGroupNames();
160: Settings.getInstance().setProperty(
161: "workbench.profiles.expandedgroups",
162: StringUtil.listToString(expandedGroups, ',', true));
163: }
164:
165: private void buildTree() {
166: this .dummyAdded = false;
167: this .model = new ProfileListModel();
168: if (model.getSize() < 1) {
169: this .model.addEmptyProfile();
170: this .dummyAdded = true;
171: }
172: this .profileTree.setModel(this .model);
173: this .connectionEditor.setSourceList(this .model);
174: }
175:
176: public ConnectionProfile getSelectedProfile() {
177: return ((ProfileTree) profileTree).getSelectedProfile();
178: }
179:
180: public void addListMouseListener(MouseListener aListener) {
181: this .listMouseListener = aListener;
182: }
183:
184: private boolean checkGroupWithProfiles(
185: DefaultMutableTreeNode groupNode) {
186: List groups = model.getGroups();
187: JPanel p = new JPanel();
188: DefaultComboBoxModel m = new DefaultComboBoxModel(groups
189: .toArray());
190: JComboBox groupBox = new JComboBox(m);
191: groupBox.setSelectedIndex(0);
192: p.setLayout(new BorderLayout(0, 5));
193: p.add(new JLabel(ResourceMgr
194: .getString("LblDeleteNonEmptyGroup")),
195: BorderLayout.NORTH);
196: p.add(groupBox, BorderLayout.SOUTH);
197: String[] options = new String[] {
198: ResourceMgr.getString("LblMoveProfiles"),
199: ResourceMgr.getString("LblDeleteProfiles") };
200:
201: Dialog parent = (Dialog) SwingUtilities.getWindowAncestor(this );
202:
203: ValidatingDialog dialog = new ValidatingDialog(parent,
204: ResourceMgr.TXT_PRODUCT_NAME, p, options);
205: WbSwingUtilities.center(dialog, parent);
206: dialog.setVisible(true);
207: if (dialog.isCancelled()) {
208: return false;
209: }
210:
211: int result = dialog.getSelectedOption();
212: if (result == 0) {
213: // move profiles
214: String group = (String) groupBox.getSelectedItem();
215: if (group == null) {
216: return false;
217: }
218:
219: model.moveProfilesToGroup(groupNode, group);
220: return true;
221: } else if (result == 1) {
222: return true;
223: }
224:
225: return false;
226: }
227:
228: /**
229: * Remove an item from the listmodel.
230: * This will also remove the profile from the ConnectionMgr's
231: * profile list.
232: */
233: public void deleteItem() throws Exception {
234: TreePath[] path = profileTree.getSelectionPaths();
235: if (path == null) {
236: return;
237: }
238: if (path.length == 0) {
239: return;
240: }
241:
242: ProfileTree tree = (ProfileTree) profileTree;
243: if (tree.onlyProfilesSelected()) {
244: DefaultMutableTreeNode group = (DefaultMutableTreeNode) path[0]
245: .getPathComponent(1);
246: DefaultMutableTreeNode firstNode = (DefaultMutableTreeNode) path[0]
247: .getLastPathComponent();
248: int newIndex = model.getIndexOfChild(group, firstNode);
249: if (newIndex > 0) {
250: newIndex--;
251: }
252:
253: for (int i = 0; i < path.length; i++) {
254: DefaultMutableTreeNode node = (DefaultMutableTreeNode) path[i]
255: .getLastPathComponent();
256: ConnectionProfile prof = (ConnectionProfile) node
257: .getUserObject();
258:
259: this .model.deleteProfile(prof);
260: }
261: if (group.getChildCount() > 0) {
262: Object newChild = model.getChild(group, newIndex);
263: TreePath newPath = new TreePath(new Object[] {
264: model.getRoot(), group, newChild });
265: ((ProfileTree) profileTree).selectPath(newPath);
266: }
267: } else // delete a group
268: {
269: DefaultMutableTreeNode node = (DefaultMutableTreeNode) path[0]
270: .getLastPathComponent();
271: if (node.getChildCount() > 0) {
272: if (!checkGroupWithProfiles(node)) {
273: return;
274: }
275: }
276: model.removeGroupNode(node);
277: }
278: }
279:
280: /**
281: * Create a new profile. This will be added to the ListModel and the
282: * ConnectionMgr's profile list.
283: */
284: public void newItem(boolean createCopy) throws Exception {
285: ConnectionProfile cp = null;
286:
287: if (createCopy) {
288: ConnectionProfile current = getSelectedProfile();
289: if (current != null) {
290: cp = current.createCopy();
291: cp.setName(ResourceMgr.getString("TxtCopyOfProfile")
292: + " " + current.getName());
293: }
294: }
295:
296: if (cp == null) {
297: cp = new ConnectionProfile();
298: cp.setUseSeparateConnectionPerTab(true);
299: cp.setName(ResourceMgr.getString("TxtEmptyProfileName"));
300: cp.setGroup(getCurrentGroup());
301: }
302: cp.setNew();
303:
304: TreePath newPath = this .model.addProfile(cp);
305: ((ProfileTree) profileTree).selectPath(newPath);
306: }
307:
308: private String getCurrentGroup() {
309: TreePath path = profileTree.getSelectionPath();
310: if (path == null) {
311: return null;
312: }
313:
314: DefaultMutableTreeNode node = null;
315: if (path.getPathCount() == 2) {
316: // group node selected
317: node = (DefaultMutableTreeNode) path.getLastPathComponent();
318: }
319: if (path.getPathCount() > 2) {
320: // Get the group of the currently selected profile;
321: node = (DefaultMutableTreeNode) path.getPathComponent(1);
322: }
323: if (node == null) {
324: return null;
325: }
326:
327: if (node.getAllowsChildren()) {
328: String g = (String) node.getUserObject();
329: return g;
330: }
331: return null;
332: }
333:
334: public void saveItem() throws Exception {
335: ConnectionMgr conn = ConnectionMgr.getInstance();
336: this .connectionEditor.updateProfile();
337: conn.saveProfiles();
338: }
339:
340: public int getProfileCount() {
341: return this .profileTree.getRowCount();
342: }
343:
344: public boolean validateInput() {
345: return this .connectionEditor.validateInput();
346: }
347:
348: public void componentDisplayed() {
349: // nothing to do
350: }
351:
352: /** This method is called from within the constructor to
353: * initialize the form.
354: * WARNING: Do NOT modify this code. The content of this method is
355: * always regenerated by the Form Editor.
356: */
357: // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
358: private void initComponents() {
359:
360: jSplitPane = new WbSplitPane();
361:
362: listPanel = new javax.swing.JPanel();
363: jScrollPane1 = new javax.swing.JScrollPane();
364: profileTree = new ProfileTree();
365:
366: FormListener formListener = new FormListener();
367:
368: setLayout(new java.awt.BorderLayout());
369:
370: jSplitPane.setBorder(javax.swing.BorderFactory
371: .createEtchedBorder());
372: jSplitPane.setDividerLocation(110);
373:
374: listPanel.setLayout(new java.awt.BorderLayout());
375:
376: jScrollPane1.setPreferredSize(null);
377:
378: profileTree.setName("profileTree"); // NOI18N
379: profileTree.addMouseListener(formListener);
380: profileTree.addTreeSelectionListener(formListener);
381: jScrollPane1.setViewportView(profileTree);
382:
383: listPanel.add(jScrollPane1, java.awt.BorderLayout.CENTER);
384:
385: jSplitPane.setLeftComponent(listPanel);
386:
387: add(jSplitPane, java.awt.BorderLayout.CENTER);
388: }
389:
390: // Code for dispatching events from components to event handlers.
391:
392: private class FormListener implements java.awt.event.MouseListener,
393: javax.swing.event.TreeSelectionListener {
394: FormListener() {
395: }
396:
397: public void mouseClicked(java.awt.event.MouseEvent evt) {
398: if (evt.getSource() == profileTree) {
399: ProfileEditorPanel.this .profileTreeMouseClicked(evt);
400: }
401: }
402:
403: public void mouseEntered(java.awt.event.MouseEvent evt) {
404: }
405:
406: public void mouseExited(java.awt.event.MouseEvent evt) {
407: }
408:
409: public void mousePressed(java.awt.event.MouseEvent evt) {
410: }
411:
412: public void mouseReleased(java.awt.event.MouseEvent evt) {
413: }
414:
415: public void valueChanged(
416: javax.swing.event.TreeSelectionEvent evt) {
417: if (evt.getSource() == profileTree) {
418: ProfileEditorPanel.this .profileTreeValueChanged(evt);
419: }
420: }
421: }// </editor-fold>//GEN-END:initComponents
422:
423: private void profileTreeMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_profileTreeMouseClicked
424:
425: if (this .listMouseListener != null) {
426: Point p = evt.getPoint();
427: TreePath path = profileTree.getClosestPathForLocation(
428: (int) p.getX(), (int) p.getY());
429: TreeNode n = (TreeNode) path.getLastPathComponent();
430: if (n.isLeaf()) {
431: this .listMouseListener.mouseClicked(evt);
432: }
433: }
434: }//GEN-LAST:event_profileTreeMouseClicked
435:
436: private void profileTreeValueChanged(
437: javax.swing.event.TreeSelectionEvent evt) {//GEN-FIRST:event_profileTreeValueChanged
438:
439: if (this .connectionEditor == null) {
440: return;
441: }
442:
443: if (evt.getSource() == this .profileTree) {
444: try {
445: ConnectionProfile newProfile = getSelectedProfile();
446: if (newProfile != null) {
447: if (!this .connectionEditor.isVisible()) {
448: this .connectionEditor.setVisible(true);
449: }
450: this .connectionEditor.setProfile(newProfile);
451: this .deleteItem.setEnabled(true);
452: this .copyItem.setEnabled(true);
453: } else {
454: TreePath p = profileTree.getSelectionPath();
455: TreeNode n = (TreeNode) (p != null ? p
456: .getLastPathComponent() : null);
457: int count = (n == null ? -1 : n.getChildCount());
458: this .connectionEditor.setVisible(false);
459: this .deleteItem.setEnabled(true);
460: this .copyItem.setEnabled(false);
461: }
462: } catch (Exception e) {
463: LogMgr.logError("ProfileEditorPanel.valueChanged()",
464: "Error selecting new profile", e);
465: }
466: }
467: }//GEN-LAST:event_profileTreeValueChanged
468:
469: // Variables declaration - do not modify//GEN-BEGIN:variables
470: protected javax.swing.JScrollPane jScrollPane1;
471: protected javax.swing.JSplitPane jSplitPane;
472: protected javax.swing.JPanel listPanel;
473: protected javax.swing.JTree profileTree;
474: // End of variables declaration//GEN-END:variables
475: }
|