2 * Copyright 2000-2007 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com
.intellij
.ui
;
18 import com
.intellij
.openapi
.application
.Application
;
19 import com
.intellij
.openapi
.application
.ApplicationManager
;
20 import com
.intellij
.openapi
.fileChooser
.FileChooser
;
21 import com
.intellij
.openapi
.fileChooser
.FileChooserDescriptor
;
22 import com
.intellij
.openapi
.fileChooser
.FileChooserDescriptorFactory
;
23 import com
.intellij
.openapi
.ui
.FixedSizeButton
;
24 import com
.intellij
.openapi
.ui
.Splitter
;
25 import com
.intellij
.openapi
.ui
.TextFieldWithBrowseButton
;
26 import com
.intellij
.openapi
.util
.io
.FileUtil
;
27 import com
.intellij
.openapi
.util
.text
.StringUtil
;
28 import com
.intellij
.openapi
.vfs
.VfsUtil
;
29 import com
.intellij
.openapi
.vfs
.VirtualFile
;
30 import com
.intellij
.util
.ArrayUtil
;
31 import com
.intellij
.util
.Consumer
;
32 import com
.intellij
.util
.ui
.UIUtil
;
33 import org
.jetbrains
.annotations
.NonNls
;
34 import org
.jetbrains
.annotations
.NotNull
;
37 import javax
.swing
.border
.Border
;
38 import javax
.swing
.border
.TitledBorder
;
39 import javax
.swing
.table
.TableCellRenderer
;
40 import javax
.swing
.table
.TableColumnModel
;
42 import java
.awt
.event
.ActionEvent
;
43 import java
.awt
.event
.ActionListener
;
44 import java
.lang
.reflect
.InvocationTargetException
;
45 import java
.net
.MalformedURLException
;
47 public class GuiUtils
{
49 private static final Insets paddingFromDialogBoundaries
= new Insets(7, 5, 7, 5);
50 private static final Insets paddingInsideDialog
= new Insets(5, 5, 5, 5);
52 public static final int lengthForFileField
= 25;
54 public static JPanel
constructFieldWithBrowseButton(JComponent aComponent
, ActionListener aActionListener
) {
55 return constructFieldWithBrowseButton(aComponent
, aActionListener
, 0);
58 public static JPanel
constructFieldWithBrowseButton(TextFieldWithHistory aComponent
, ActionListener aActionListener
) {
59 return constructFieldWithBrowseButton(aComponent
, aActionListener
, 0);
62 private static JPanel
constructFieldWithBrowseButton(final JComponent aComponent
, final ActionListener aActionListener
, int delta
) {
63 JPanel result
= new JPanel(new GridBagLayout());
64 result
.add(aComponent
, new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints
.CENTER
, GridBagConstraints
.BOTH
, new Insets(0, 0, 0, 0), 0,0));
65 FixedSizeButton browseButton
= new FixedSizeButton(aComponent
.getPreferredSize().height
- delta
);//ignore border in case of browse button
66 TextFieldWithBrowseButton
.MyDoClickAction
.addTo(browseButton
, aComponent
);
67 result
.add(browseButton
, new GridBagConstraints(1, 0, 1, 1, 0, 1, GridBagConstraints
.CENTER
, GridBagConstraints
.NONE
, new Insets(0,0,0,0), 0,0));
68 browseButton
.addActionListener(aActionListener
);
73 public static JPanel
constructDirectoryBrowserField(final JTextField aTextField
, final String aSearchedObjectName
) {
74 return constructFieldWithBrowseButton(aTextField
, new ActionListener() {
75 public void actionPerformed(ActionEvent e
) {
76 FileChooserDescriptor descriptor
= FileChooserDescriptorFactory
.getDirectoryChooserDescriptor(aSearchedObjectName
);
77 VirtualFile
[] files
= FileChooser
.chooseFiles(aTextField
, descriptor
);
78 if (files
.length
!= 0) {
79 aTextField
.setText(FileUtil
.toSystemDependentName(files
[0].getPath()));
80 aTextField
.postActionEvent();
86 public static JPanel
constructFileURLBrowserField(final TextFieldWithHistory aFieldWithHistory
,
87 final String aSearchedObjectName
) {
88 return constructFieldWithBrowseButton(aFieldWithHistory
, new ActionListener() {
89 public void actionPerformed(ActionEvent e
) {
90 FileChooserDescriptor descriptor
= FileChooserDescriptorFactory
.getFileChooserDescriptor(aSearchedObjectName
);
91 VirtualFile
[] files
= FileChooser
.chooseFiles(aFieldWithHistory
, descriptor
);
92 if (files
.length
!= 0) {
94 aFieldWithHistory
.setText(VfsUtil
.virtualToIoFile(files
[0]).toURL().toString());
96 catch (MalformedURLException e1
) {
97 aFieldWithHistory
.setText("");
104 public static JComponent
constructLabeledComponent(String aLabelText
, JComponent aComponent
, int aAxis
) {
105 JPanel result
= new JPanel();
106 BoxLayout boxLayout
= new BoxLayout(result
, aAxis
);
107 result
.setLayout(boxLayout
);
109 result
.add(new JLabel(aLabelText
));
110 result
.add(aComponent
);
115 public static JPanel
makeDialogPanel(JPanel aPanel
) {
116 JPanel emptyBordered
= makePaddedPanel(aPanel
, paddingFromDialogBoundaries
);
117 return wrapWithBorder(emptyBordered
, IdeBorderFactory
.createBorder());
120 public static JPanel
makeTitledPanel(JComponent aComponent
, String aTitle
) {
121 JPanel result
= makePaddedPanel(aComponent
, false, true, false, true);
122 return wrapWithBorder(result
, IdeBorderFactory
.createTitledBorder(aTitle
));
126 private static JPanel
wrapWithBorder(JComponent aPanel
, Border aBorder
) {
127 JPanel wrapper
= new JPanel(new BorderLayout());
128 wrapper
.add(aPanel
, BorderLayout
.CENTER
);
129 wrapper
.setBorder(aBorder
);
134 public static BorderLayout
createBorderLayout() {
135 return new BorderLayout(paddingInsideDialog
.left
, paddingInsideDialog
.top
);
138 public static GridLayout
createGridLayout(int aRows
, int aColumns
) {
139 return new GridLayout(aRows
, aColumns
, paddingInsideDialog
.left
, paddingInsideDialog
.top
);
142 public static Component
createVerticalStrut() {
143 return Box
.createRigidArea(new Dimension(0, paddingInsideDialog
.top
));
146 public static Component
createHorisontalStrut() {
147 return Box
.createRigidArea(new Dimension(paddingInsideDialog
.left
, 0));
150 private static JPanel
makePaddedPanel(JComponent aComponent
, Insets aInsets
) {
151 return wrapWithBorder(aComponent
, BorderFactory
.createEmptyBorder(
159 private static JPanel
makePaddedPanel(JComponent aComponent
,
164 return wrapWithBorder(aComponent
, BorderFactory
.createEmptyBorder(
165 aTop ? paddingInsideDialog
.top
: 0,
166 aLeft ? paddingInsideDialog
.left
: 0,
167 aBottom ? paddingInsideDialog
.bottom
: 0,
168 aRight ? paddingInsideDialog
.right
: 0));
171 public static void setAdditionalIcon(JRadioButton button
, Icon icon
) {
172 final Icon defaultIcon
= UIUtil
.getRadioButtonIcon();
173 LayeredIcon deficon
= new LayeredIcon(2);
174 deficon
.setIcon(defaultIcon
, 0);
175 deficon
.setIcon(icon
, 1, defaultIcon
.getIconWidth() + 5, 0);
176 button
.setIcon(deficon
);
178 LayeredIcon pressed
= new LayeredIcon(2);
179 pressed
.setIcon(defaultIcon
, 0);
180 pressed
.setIcon(icon
, 1, defaultIcon
.getIconWidth() + 5, 0);
181 button
.setPressedIcon(pressed
);
183 LayeredIcon selected
= new LayeredIcon(2);
184 selected
.setIcon(defaultIcon
, 0);
185 selected
.setIcon(icon
, 1, defaultIcon
.getIconWidth() + 5, 0);
186 button
.setSelectedIcon(selected
);
189 public static String
getTextWithoutMnemonicEscaping(String text
) {
190 return text
.replaceAll("&", "");
193 public static char getDisplayedMnemonic(String text
) {
194 final int i
= getDisplayedMnemonicIndex(text
);
195 return i
== -1 ?
(char)-1 : text
.charAt(i
+ 1);
198 public static int getDisplayedMnemonicIndex(String text
) {
199 return text
.indexOf("&");
202 public static void packParentDialog(Component component
) {
203 while (component
!= null) {
204 if (component
instanceof JDialog
) {
205 component
.setVisible(true);
208 component
= component
.getParent();
212 public static void replaceJSplitPaneWithIDEASplitter(JComponent root
) {
213 final Container parent
= root
.getParent();
214 if (root
instanceof JSplitPane
) {
215 // we can painlessly replace only splitter which is the only child in container
216 if (parent
.getComponents().length
!= 1 && !(parent
instanceof Splitter
)) {
219 final JSplitPane pane
= (JSplitPane
)root
;
220 final Component component1
= pane
.getTopComponent();
221 final Component component2
= pane
.getBottomComponent();
222 final int orientation
= pane
.getOrientation();
223 final Splitter splitter
= new Splitter(orientation
== JSplitPane
.VERTICAL_SPLIT
);
224 splitter
.setFirstComponent((JComponent
) component1
);
225 splitter
.setSecondComponent((JComponent
) component2
);
226 splitter
.setShowDividerControls(pane
.isOneTouchExpandable());
227 splitter
.setHonorComponentsMinimumSize(true);
229 if (pane
.getDividerLocation() > 0) {
230 // let the component chance to resize itself
231 SwingUtilities
.invokeLater(new Runnable() {
234 if (pane
.getOrientation() == JSplitPane
.VERTICAL_SPLIT
) {
235 proportion
= pane
.getDividerLocation() / (double)(parent
.getHeight() - pane
.getDividerSize());
238 proportion
= pane
.getDividerLocation() / (double)(parent
.getWidth() - pane
.getDividerSize());
240 if (proportion
> 0 && proportion
< 1) {
241 splitter
.setProportion((float)proportion
);
247 if (parent
instanceof Splitter
) {
248 final Splitter psplitter
= (Splitter
) parent
;
249 if (psplitter
.getFirstComponent() == root
)
250 psplitter
.setFirstComponent(splitter
);
252 psplitter
.setSecondComponent(splitter
);
256 parent
.setLayout(new BorderLayout());
257 parent
.add(splitter
, BorderLayout
.CENTER
);
259 replaceJSplitPaneWithIDEASplitter((JComponent
) component1
);
260 replaceJSplitPaneWithIDEASplitter((JComponent
) component2
);
263 final Component
[] components
= root
.getComponents();
264 for (Component component
: components
) {
265 if (component
instanceof JComponent
) {
266 replaceJSplitPaneWithIDEASplitter((JComponent
)component
);
272 public static void iterateChildren(Component container
, Consumer
<Component
> consumer
, JComponent
... excludeComponents
) {
273 if (excludeComponents
!= null && ArrayUtil
.find(excludeComponents
, container
) != -1) return;
274 consumer
.consume(container
);
275 if (container
instanceof Container
) {
276 final Component
[] components
= ((Container
)container
).getComponents();
277 for (Component child
: components
) {
278 iterateChildren(child
, consumer
, excludeComponents
);
283 public static void iterateChildren(Consumer
<Component
> consumer
, Component
... components
) {
284 for (final Component component
: components
) {
285 iterateChildren(component
, consumer
);
289 public static void enableChildren(final boolean enabled
, Component
... components
) {
290 for (final Component component
: components
) {
291 enableChildren(component
, enabled
);
295 public static void showComponents(final boolean visible
, Component
... components
) {
296 for (final Component component
: components
) {
297 component
.setVisible(visible
);
301 public static void enableChildren(Component container
, final boolean enabled
, JComponent
... excludeComponents
) {
302 iterateChildren(container
, new Consumer
<Component
>() {
303 public void consume(final Component t
) {
304 enableComponent(t
, enabled
);
306 }, excludeComponents
);
309 private static void enableComponent(Component component
, boolean enabled
) {
310 if (component
.isEnabled() == enabled
) return;
311 component
.setEnabled(enabled
);
312 if (component
instanceof JPanel
) {
313 final Border border
= ((JPanel
)component
).getBorder();
314 if (border
instanceof TitledBorder
) {
315 Color color
= enabled ? component
.getForeground() : UIUtil
.getTextInactiveTextColor();
316 ((TitledBorder
)border
).setTitleColor(color
);
319 else if (component
instanceof JLabel
) {
320 Color color
= UIUtil
.getTextInactiveTextColor();
321 if (color
== null) color
= component
.getForeground();
322 @NonNls String changeColorString
= "<font color=#" + colorToHex(color
) +">";
323 final JLabel label
= (JLabel
)component
;
324 @NonNls String text
= label
.getText();
325 if (text
!= null && text
.startsWith("<html>")) {
326 if (StringUtil
.startsWithConcatenationOf(text
, "<html>", changeColorString
) && enabled
) {
327 text
= "<html>"+text
.substring(("<html>"+changeColorString
).length());
329 else if (!StringUtil
.startsWithConcatenationOf(text
, "<html>", changeColorString
) && !enabled
) {
330 text
= "<html>"+changeColorString
+text
.substring("<html>".length());
335 else if (component
instanceof JTable
) {
336 TableColumnModel columnModel
= ((JTable
)component
).getColumnModel();
337 for (int i
=0; i
<columnModel
.getColumnCount();i
++) {
338 TableCellRenderer cellRenderer
= columnModel
.getColumn(0).getCellRenderer();
339 if (cellRenderer
instanceof Component
) {
340 enableComponent((Component
)cellRenderer
, enabled
);
346 public static String
colorToHex(final Color color
) {
347 return to2DigitsHex(color
.getRed())
348 +to2DigitsHex(color
.getGreen())
349 +to2DigitsHex(color
.getBlue());
352 private static String
to2DigitsHex(int i
) {
353 String s
= Integer
.toHexString(i
);
354 if (s
.length() < 2) s
= "0" + s
;
358 public static void invokeAndWait(@NotNull Runnable runnable
) throws InvocationTargetException
, InterruptedException
{
359 Application application
= ApplicationManager
.getApplication();
360 assert !application
.isDispatchThread() : "Must not be invoked from AWT dispatch thread";
361 if (application
.isReadAccessAllowed()) {
362 // make ApplicationImpl catch deadlock situation with readLock held
363 application
.invokeAndWait(runnable
, application
.getDefaultModalityState());
366 SwingUtilities
.invokeAndWait(runnable
);
368 public static void runOrInvokeAndWait(@NotNull Runnable runnable
) throws InvocationTargetException
, InterruptedException
{
369 Application application
= ApplicationManager
.getApplication();
370 if (application
.isDispatchThread()) {
374 invokeAndWait(runnable
);