001: package Schmortopf.JavaSourceEditor.DocumentHistoryTracker;
002:
003: /**
004: * The view of the DocumentHistoryTracker model.
005: * This view is completely managed by the model itself.
006: */
007: import java.awt.*;
008: import java.awt.event.*;
009: import javax.swing.*;
010: import javax.swing.border.Border;
011: import java.util.Vector;
012:
013: import Schmortopf.Utility.gui.*;
014: import Schmortopf.Utility.StringUtilities;
015:
016: public class DocumentHistoryTrackerView extends DocumentTrackerView {
017:
018: private JPanel parentView; // The panel, to which this view
019: // can connect or disconnect.
020:
021: private DocumentButtonPanelModel model;
022:
023: private JSmoothToggleButton[] viewButtons = new JSmoothToggleButton[0];
024:
025: private int currentPosition = -1; // none selected initially
026:
027: private JPanel viewMainPanel;
028:
029: private String viewTitle;
030:
031: // This flag is needed, because the updateUI() method sometimes
032: // is initially called, when some referenced UIManager
033: // functionality is not available yet. DO NOT REMOVE THIS.
034: private boolean allIsReadyForSpecialUpdates = false;
035:
036: private EditorDocumentHistoryTracker editorDocumentHistoryTracker;
037:
038: public DocumentHistoryTrackerView(
039: final EditorDocumentHistoryTracker editorDocumentHistoryTracker,
040: final JPanel parentView,
041: final DocumentButtonPanelModel model, final String viewTitle) {
042: this .editorDocumentHistoryTracker = editorDocumentHistoryTracker;
043: this .parentView = parentView;
044: this .model = model;
045: this .viewTitle = viewTitle;
046: this .setLayout(new BorderLayout(0, 0));
047: this .viewMainPanel = new JPanel(new FlowLayout(FlowLayout.LEFT,
048: 0, 0));
049: this .add(this .viewMainPanel, BorderLayout.CENTER);
050: this .updateView(); // Initial power up
051: EventQueue.invokeLater(new Runnable() {
052: public void run() {
053: allIsReadyForSpecialUpdates = true;
054: updateSpecialUI();
055: }
056: });
057: } // Constructor
058:
059: /**
060: * Called by the model, when the history has changed.
061: */
062: public void viewChanged(Vector documentHistoryVector,
063: int theCurrentPosition) {
064: this .currentPosition = theCurrentPosition;
065: DocumentHistoryEntry entry;
066: String buttonText = null;
067: this .viewButtons = new JSmoothToggleButton[documentHistoryVector
068: .size()];
069: String[] tokens;
070: for (int i = 0; i < documentHistoryVector.size(); i++) {
071: entry = (DocumentHistoryEntry) documentHistoryVector
072: .elementAt(i);
073: // lib files carry the whole local jarentry path as name, therefore
074: // only take the last token :
075: tokens = StringUtilities.SplitString(entry.getName(), "/");
076: buttonText = tokens[tokens.length - 1];
077: if (buttonText.endsWith(".java")) // skips this ending for projectfiles
078: buttonText = buttonText.substring(0, buttonText
079: .length() - 5);
080: // Add this full name as toolTipText :
081: String toolTipText = buttonText;
082: // but cut it for the button caption, if it's very long :
083: if (buttonText.length() > 24)
084: buttonText = buttonText.substring(0, 22) + "..";
085: this .viewButtons[i] = new JSmoothToggleButton(buttonText);
086: this .viewButtons[i].setIcon(entry.getIcon());
087: this .viewButtons[i].setFontIdentifier("Tree.font");
088: this .viewButtons[i].setToolTipText(toolTipText);
089: this .viewButtons[i].setDoPaintBorders(false);
090: // Set the selection state, BEFORE we add the listener - it mustn't launch :
091: this .viewButtons[i]
092: .setSelected((i == this .currentPosition));
093: final int buttonIndex = i;
094: final DocumentHistoryEntry finalEntry = entry;
095: this .viewButtons[i].addMouseListener(new MouseAdapter() {
096: // Note: We launch the action already on mousePressed.
097: // Reason is, that often the programmer is quite fast at this location
098: // and the cursor might have left the button region when the button
099: // goes up, so mouseClicked() wouldn't start in that case.
100: public void mousePressed(MouseEvent e) {
101: // Distinguish left and right mousebutton click :
102: if ((e.getModifiers() & (e.BUTTON2_MASK | e.BUTTON3_MASK)) != 0) {
103: // Right mousebutton : Move to first entry and select :
104: model.checkRemoveEntry(finalEntry.getPath(),
105: finalEntry.getName());
106: currentPosition = 0;
107: model.addNewFileDocument(finalEntry, false,
108: false);
109: model.selectDocumentWithIndex(0);
110: } else {
111: // Left mousebutton : Just select
112: model.selectDocumentWithIndex(buttonIndex);
113: }
114: // The projectfile links tree selection gets out of sync,
115: // so we clear it:
116: editorDocumentHistoryTracker
117: .clearSelectionsInProjectFilesLinkTree();
118: }
119: });
120: }
121: this .updateView();
122: }
123:
124: private void updateView() {
125: // Remove all JComponents :
126: int i = 0;
127: while (i < this .viewMainPanel.getComponentCount()) {
128: Component c = this .viewMainPanel.getComponent(i);
129: if (c instanceof JComponent) {
130: this .viewMainPanel.remove(i);
131: } else {
132: i++;
133: }
134: }
135: int charSize = UIManager.getFont("Tree.font").getSize();
136: int gap = charSize / 2;
137: // Add the title label :
138: JContrastLabel titleLabel = new JContrastLabel(this .viewTitle);
139: titleLabel.setBorder(BorderFactory.createEmptyBorder(gap / 6,
140: gap, gap / 6, gap));
141: titleLabel.setFont(UIManager.getFont("Menu.font"));
142: this .viewMainPanel.add(titleLabel);
143: // And reset the history buttons :
144: for (i = 0; i < this .viewButtons.length; i++) {
145: this .viewMainPanel.add(this .viewButtons[i]);
146: this .viewButtons[i].setFont(UIManager.getFont("Tree.font"));
147: }
148: parentView.updateUI();
149: } // historyChanged
150:
151: /**
152: * Process additional update-work, after having called
153: * the parent method.
154: */
155: public void updateUI() {
156: super .updateUI();
157: // additional updates :
158: if (this .allIsReadyForSpecialUpdates) {
159: EventQueue.invokeLater(new Runnable() {
160: public void run() {
161: updateSpecialUI();
162: }
163: });
164: }
165: }
166:
167: /**
168: * Called by this class itself on LF changes and once after construction.
169: */
170: public void updateSpecialUI() {
171: Color darkerColor = UIManager.getColor("Menu.background")
172: .darker();
173: Color brighterColor = UIManager.getColor("Menu.background")
174: .brighter();
175: this .setBorder(new CustomEtchedBorder(false, false, true,
176: false, brighterColor, darkerColor));
177: this .viewChanged(this .model.getButtonVector(), this .model
178: .getCurrentIndex());
179: }
180:
181: /**
182: * Called by the model, when the active position has changed.
183: */
184: public void currentPositionChanged(int newPosition) {
185: if ((newPosition >= 0)
186: && (newPosition < this .viewButtons.length)) {
187: this .currentPosition = newPosition;
188: synchronized (this .viewButtons) {
189: for (int i = 0; i < this .viewButtons.length; i++) {
190: this .viewButtons[i].setSelected((newPosition == i));
191: }
192: }
193: }
194: } // currentPositionChanged
195:
196: /**
197: * Connect this view to the parentView.
198: */
199: public void connect() {
200: this .parentView.add(this , BorderLayout.CENTER);
201: this .viewChanged(model.getButtonVector(), model
202: .getCurrentIndex());
203: this .parentView.getParent().getParent().getParent().getParent()
204: .getParent().validate();
205: }
206:
207: /**
208: * Disconnect this view from the parentView.
209: */
210: public void disconnect() {
211: this .parentView.remove(this );
212: this .parentView.getParent().getParent().getParent().getParent()
213: .getParent().validate();
214: }
215:
216: /**
217: * GC assistance. Called when the object isn't used nevermore.
218: */
219: public void terminate() {
220: this .parentView = null;
221: for (int i = 0; i < this .viewButtons.length; i++) {
222: this .viewButtons[i] = null;
223: }
224: this .viewButtons = null;
225: }
226:
227: } // DocumentHistoryTrackerView
|