38 |
|
|
39 |
package javax.swing.plaf.metal; |
package javax.swing.plaf.metal; |
40 |
|
|
41 |
|
import java.awt.Color; |
42 |
|
import java.awt.Component; |
43 |
import java.awt.Container; |
import java.awt.Container; |
44 |
import java.awt.Dimension; |
import java.awt.Dimension; |
45 |
import java.awt.Graphics; |
import java.awt.Graphics; |
46 |
|
import java.awt.Insets; |
47 |
import java.awt.LayoutManager; |
import java.awt.LayoutManager; |
48 |
|
import java.awt.Rectangle; |
49 |
|
import java.beans.PropertyChangeEvent; |
50 |
|
import java.beans.PropertyChangeListener; |
51 |
|
|
52 |
import javax.swing.Icon; |
import javax.swing.Icon; |
53 |
import javax.swing.JInternalFrame; |
import javax.swing.JInternalFrame; |
54 |
|
import javax.swing.JLabel; |
55 |
import javax.swing.JMenu; |
import javax.swing.JMenu; |
56 |
|
import javax.swing.SwingConstants; |
57 |
|
import javax.swing.SwingUtilities; |
58 |
|
import javax.swing.UIDefaults; |
59 |
|
import javax.swing.UIManager; |
60 |
import javax.swing.plaf.basic.BasicInternalFrameTitlePane; |
import javax.swing.plaf.basic.BasicInternalFrameTitlePane; |
61 |
|
|
62 |
|
|
63 |
/** |
/** |
64 |
* The title pane for a {@link JInternalFrame}. |
* The title pane for a {@link JInternalFrame}. This can be displayed in two |
65 |
|
* styles: one for regular internal frames, and the other for "palette" style |
66 |
|
* internal frames. |
67 |
*/ |
*/ |
68 |
public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane |
public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane |
69 |
{ |
{ |
70 |
|
|
71 |
|
/** |
72 |
|
* A property change handler that listens for changes to the |
73 |
|
* <code>JInternalFrame.isPalette</code> property and updates the title |
74 |
|
* pane as appropriate. |
75 |
|
*/ |
76 |
|
class MetalInternalFrameTitlePanePropertyChangeHandler |
77 |
|
extends PropertyChangeHandler |
78 |
|
{ |
79 |
|
/** |
80 |
|
* Creates a new handler. |
81 |
|
*/ |
82 |
|
public MetalInternalFrameTitlePanePropertyChangeHandler() |
83 |
|
{ |
84 |
|
super(); |
85 |
|
} |
86 |
|
|
87 |
|
/** |
88 |
|
* Handles <code>JInternalFrame.isPalette</code> property changes, with all |
89 |
|
* other propert changes being passed to the superclass. |
90 |
|
* |
91 |
|
* @param e the event. |
92 |
|
*/ |
93 |
|
public void propertyChange(PropertyChangeEvent e) |
94 |
|
{ |
95 |
|
String propName = e.getPropertyName(); |
96 |
|
if (propName.equals("JInternalFrame.isPalette")) |
97 |
|
{ |
98 |
|
if (e.getNewValue().equals(Boolean.TRUE)) |
99 |
|
setPalette(true); |
100 |
|
else |
101 |
|
setPalette(false); |
102 |
|
} |
103 |
|
else |
104 |
|
super.propertyChange(e); |
105 |
|
} |
106 |
|
} |
107 |
|
|
108 |
|
/** |
109 |
|
* A layout manager for the title pane. |
110 |
|
* |
111 |
|
* @see #createLayout() |
112 |
|
*/ |
113 |
|
private class MetalTitlePaneLayout implements LayoutManager |
114 |
|
{ |
115 |
|
/** |
116 |
|
* Creates a new <code>TitlePaneLayout</code> object. |
117 |
|
*/ |
118 |
|
public MetalTitlePaneLayout() |
119 |
|
{ |
120 |
|
// Do nothing. |
121 |
|
} |
122 |
|
|
123 |
|
/** |
124 |
|
* Adds a Component to the Container. |
125 |
|
* |
126 |
|
* @param name The name to reference the added Component by. |
127 |
|
* @param c The Component to add. |
128 |
|
*/ |
129 |
|
public void addLayoutComponent(String name, Component c) |
130 |
|
{ |
131 |
|
// Do nothing. |
132 |
|
} |
133 |
|
|
134 |
|
/** |
135 |
|
* This method is called to lay out the children of the Title Pane. |
136 |
|
* |
137 |
|
* @param c The Container to lay out. |
138 |
|
*/ |
139 |
|
public void layoutContainer(Container c) |
140 |
|
{ |
141 |
|
|
142 |
|
Dimension size = c.getSize(); |
143 |
|
Insets insets = c.getInsets(); |
144 |
|
int width = size.width - insets.left - insets.right; |
145 |
|
int height = size.height - insets.top - insets.bottom; |
146 |
|
|
147 |
|
|
148 |
|
int loc = width - insets.right - 1; |
149 |
|
int top = insets.top + 2; |
150 |
|
int buttonHeight = height - 4; |
151 |
|
if (closeButton.isVisible()) |
152 |
|
{ |
153 |
|
int buttonWidth = closeIcon.getIconWidth(); |
154 |
|
loc -= buttonWidth + 2; |
155 |
|
closeButton.setBounds(loc, top, buttonWidth, buttonHeight); |
156 |
|
loc -= 6; |
157 |
|
} |
158 |
|
|
159 |
|
if (maxButton.isVisible()) |
160 |
|
{ |
161 |
|
int buttonWidth = maxIcon.getIconWidth(); |
162 |
|
loc -= buttonWidth + 4; |
163 |
|
maxButton.setBounds(loc, top, buttonWidth, buttonHeight); |
164 |
|
} |
165 |
|
|
166 |
|
if (iconButton.isVisible()) |
167 |
|
{ |
168 |
|
int buttonWidth = minIcon.getIconWidth(); |
169 |
|
loc -= buttonWidth + 4; |
170 |
|
iconButton.setBounds(loc, top, buttonWidth, buttonHeight); |
171 |
|
loc -= 2; |
172 |
|
} |
173 |
|
|
174 |
|
Dimension titlePreferredSize = title.getPreferredSize(); |
175 |
|
title.setBounds(insets.left + 5, insets.top, |
176 |
|
Math.min(titlePreferredSize.width, loc - insets.left - 10), |
177 |
|
height); |
178 |
|
|
179 |
|
} |
180 |
|
|
181 |
|
/** |
182 |
|
* This method returns the minimum size of the given Container given the |
183 |
|
* children that it has. |
184 |
|
* |
185 |
|
* @param c The Container to get a minimum size for. |
186 |
|
* |
187 |
|
* @return The minimum size of the Container. |
188 |
|
*/ |
189 |
|
public Dimension minimumLayoutSize(Container c) |
190 |
|
{ |
191 |
|
return preferredLayoutSize(c); |
192 |
|
} |
193 |
|
|
194 |
|
/** |
195 |
|
* Returns the preferred size of the given Container taking |
196 |
|
* into account the children that it has. |
197 |
|
* |
198 |
|
* @param c The Container to lay out. |
199 |
|
* |
200 |
|
* @return The preferred size of the Container. |
201 |
|
*/ |
202 |
|
public Dimension preferredLayoutSize(Container c) |
203 |
|
{ |
204 |
|
if (isPalette) |
205 |
|
return new Dimension(paletteTitleHeight, paletteTitleHeight); |
206 |
|
else |
207 |
|
return new Dimension(22, 22); |
208 |
|
} |
209 |
|
|
210 |
|
/** |
211 |
|
* Removes a Component from the Container. |
212 |
|
* |
213 |
|
* @param c The Component to remove. |
214 |
|
*/ |
215 |
|
public void removeLayoutComponent(Component c) |
216 |
|
{ |
217 |
|
} |
218 |
|
} |
219 |
|
|
220 |
|
/** A flag indicating whether the title pane uses the palette style. */ |
221 |
protected boolean isPalette; |
protected boolean isPalette; |
222 |
|
|
223 |
protected Icon paletteCloseIcon = MetalIconFactory.getInternalFrameCloseIcon(16); |
/** |
224 |
|
* The icon used for the close button - this is fetched from the look and |
225 |
|
* feel defaults using the key <code>InternalFrame.paletteCloseIcon</code>. |
226 |
|
*/ |
227 |
|
protected Icon paletteCloseIcon; |
228 |
|
|
229 |
|
/** |
230 |
|
* The height of the title pane when <code>isPalette</code> is |
231 |
|
* <code>true</code>. This value is fetched from the look and feel defaults |
232 |
|
* using the key <code>InternalFrame.paletteTitleHeight</code>. |
233 |
|
*/ |
234 |
|
protected int paletteTitleHeight; |
235 |
|
|
236 |
|
/** The label used to display the title for the internal frame. */ |
237 |
|
private JLabel title; |
238 |
|
|
|
protected int paletteTitleHeight = 12; |
|
|
|
|
239 |
/** |
/** |
240 |
* Creates a new title pane. |
* Creates a new title pane for the specified frame. |
241 |
* |
* |
242 |
* @param f the internal frame. |
* @param f the internal frame. |
243 |
*/ |
*/ |
257 |
selectedTitleColor = MetalLookAndFeel.getWindowTitleBackground(); |
selectedTitleColor = MetalLookAndFeel.getWindowTitleBackground(); |
258 |
notSelectedTextColor = MetalLookAndFeel.getInactiveControlTextColor(); |
notSelectedTextColor = MetalLookAndFeel.getInactiveControlTextColor(); |
259 |
notSelectedTitleColor = MetalLookAndFeel.getWindowTitleInactiveBackground(); |
notSelectedTitleColor = MetalLookAndFeel.getWindowTitleInactiveBackground(); |
260 |
|
|
261 |
|
UIDefaults defaults = UIManager.getLookAndFeelDefaults(); |
262 |
|
paletteTitleHeight = defaults.getInt("InternalFrame.paletteTitleHeight"); |
263 |
|
paletteCloseIcon = defaults.getIcon("InternalFrame.paletteCloseIcon"); |
264 |
|
minIcon = MetalIconFactory.getInternalFrameAltMaximizeIcon(16); |
265 |
|
|
266 |
|
title = new JLabel(frame.getTitle(), |
267 |
|
MetalIconFactory.getInternalFrameDefaultMenuIcon(), |
268 |
|
SwingConstants.LEFT); |
269 |
} |
} |
270 |
|
|
271 |
/** |
/** |
278 |
selectedTitleColor = null; |
selectedTitleColor = null; |
279 |
notSelectedTextColor = null; |
notSelectedTextColor = null; |
280 |
notSelectedTitleColor = null; |
notSelectedTitleColor = null; |
281 |
|
paletteCloseIcon = null; |
282 |
|
minIcon = null; |
283 |
|
title = null; |
284 |
} |
} |
285 |
|
|
286 |
/** |
/** |
315 |
// do nothing |
// do nothing |
316 |
} |
} |
317 |
|
|
318 |
|
protected void addSubComponents() |
319 |
|
{ |
320 |
|
// FIXME: this method is probably overridden to only add the required |
321 |
|
// buttons |
322 |
|
add(title); |
323 |
|
add(closeButton); |
324 |
|
add(iconButton); |
325 |
|
add(maxButton); |
326 |
|
} |
327 |
|
|
328 |
/** |
/** |
329 |
* Creates a layout manager for the components in the title pane. |
* Creates a new instance of {@link MetalTitlePaneLayout}. |
330 |
* |
* |
331 |
* @return A layout manager. |
* @return A new instance of {@link MetalTitlePaneLayout}. |
332 |
*/ |
*/ |
333 |
protected LayoutManager createLayout() |
protected LayoutManager createLayout() |
334 |
{ |
{ |
335 |
return new TitlePaneLayout() |
return new MetalTitlePaneLayout(); |
|
{ |
|
|
public Dimension preferredLayoutSize(Container c) |
|
|
{ |
|
|
return new Dimension(24, 24); |
|
|
} |
|
|
}; |
|
336 |
} |
} |
337 |
|
|
338 |
|
/** |
339 |
|
* Draws the title pane in the palette style. |
340 |
|
* |
341 |
|
* @param g the graphics device. |
342 |
|
* |
343 |
|
* @see #paintComponent(Graphics) |
344 |
|
*/ |
345 |
public void paintPalette(Graphics g) |
public void paintPalette(Graphics g) |
346 |
{ |
{ |
347 |
// FIXME: needs implementing |
Color savedColor = g.getColor(); |
348 |
// most likely this is equivalent to paintComponent(g) when the isPalette |
Rectangle b = SwingUtilities.getLocalBounds(this); |
349 |
// flag is true |
g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); |
350 |
|
g.fillRect(b.x, b.y, b.width, b.height); |
351 |
|
MetalUtils.fillMetalPattern(g, b.x + 4, b.y + 2, b.width |
352 |
|
- paletteCloseIcon.getIconWidth() - 13, b.height - 5, |
353 |
|
MetalLookAndFeel.getPrimaryControlHighlight(), |
354 |
|
MetalLookAndFeel.getBlack()); |
355 |
|
|
356 |
|
// draw a line separating the title pane from the frame content |
357 |
|
Dimension d = getSize(); |
358 |
|
g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); |
359 |
|
g.drawLine(0, d.height - 1, d.width - 1, d.height - 1); |
360 |
|
|
361 |
|
g.setColor(savedColor); |
362 |
} |
} |
363 |
|
|
364 |
|
/** |
365 |
|
* Paints a representation of the current state of the internal frame. |
366 |
|
* |
367 |
|
* @param g the graphics device. |
368 |
|
*/ |
369 |
public void paintComponent(Graphics g) |
public void paintComponent(Graphics g) |
370 |
{ |
{ |
371 |
// probably need to check the isPalette flag here, if true pass over to |
Color savedColor = g.getColor(); |
372 |
// paintPalette(Graphics) |
if (isPalette) |
373 |
super.paintComponent(g); |
paintPalette(g); |
|
Dimension d = getSize(); |
|
|
if (frame.isSelected()) |
|
|
g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); |
|
374 |
else |
else |
375 |
g.setColor(MetalLookAndFeel.getControlDarkShadow()); |
{ |
376 |
g.drawLine(0, d.height - 1, d.width - 1, d.height - 1); |
paintTitleBackground(g); |
377 |
|
paintChildren(g); |
378 |
|
Dimension d = getSize(); |
379 |
|
if (frame.isSelected()) |
380 |
|
g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); |
381 |
|
else |
382 |
|
g.setColor(MetalLookAndFeel.getControlDarkShadow()); |
383 |
|
|
384 |
|
// put a dot in each of the top corners |
385 |
|
g.drawLine(0, 0, 0, 0); |
386 |
|
g.drawLine(d.width - 1, 0, d.width - 1, 0); |
387 |
|
|
388 |
|
g.drawLine(0, d.height - 1, d.width - 1, d.height - 1); |
389 |
|
|
390 |
|
// draw the metal pattern |
391 |
|
Rectangle b = title.getBounds(); |
392 |
|
int startX = b.x + b.width + 5; |
393 |
|
int endX = startX; |
394 |
|
if (iconButton.isVisible()) |
395 |
|
endX = Math.max(iconButton.getX(), endX); |
396 |
|
else if (maxButton.isVisible()) |
397 |
|
endX = Math.max(maxButton.getX(), endX); |
398 |
|
else if (closeButton.isVisible()) |
399 |
|
endX = Math.max(closeButton.getX(), endX); |
400 |
|
endX -= 7; |
401 |
|
if (endX > startX) |
402 |
|
MetalUtils.fillMetalPattern(g, startX, 3, endX - startX, getHeight() - 6, Color.white, Color.gray); |
403 |
|
} |
404 |
|
g.setColor(savedColor); |
405 |
} |
} |
406 |
|
|
407 |
|
/** |
408 |
|
* Sets the flag that controls whether the title pane is drawn in the |
409 |
|
* palette style or the regular style. |
410 |
|
* |
411 |
|
* @param b the new value of the flag. |
412 |
|
*/ |
413 |
public void setPalette(boolean b) |
public void setPalette(boolean b) |
414 |
{ |
{ |
415 |
isPalette = b; |
isPalette = b; |
416 |
|
title.setVisible(!isPalette); |
417 |
|
iconButton.setVisible(!isPalette && frame.isIconifiable()); |
418 |
|
maxButton.setVisible(!isPalette && frame.isMaximizable()); |
419 |
|
if (isPalette) |
420 |
|
closeButton.setIcon(paletteCloseIcon); |
421 |
|
else |
422 |
|
closeButton.setIcon(closeIcon); |
423 |
|
} |
424 |
|
|
425 |
|
protected PropertyChangeListener createPropertyChangeListener() |
426 |
|
{ |
427 |
|
return new MetalInternalFrameTitlePanePropertyChangeHandler(); |
428 |
} |
} |
429 |
} |
} |
430 |
|
|