GuiHelper.java
001 /* This file is part of the project "Hilbert II" - http://www.qedeq.org
002  *
003  * Copyright 2000-2011,  Michael Meyling <mime@qedeq.org>.
004  *
005  * "Hilbert II" is free software; you can redistribute
006  * it and/or modify it under the terms of the GNU General Public
007  * License as published by the Free Software Foundation; either
008  * version 2 of the License, or (at your option) any later version.
009  *
010  * This program is distributed in the hope that it will be useful,
011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013  * GNU General Public License for more details.
014  */
015 
016 package org.qedeq.gui.se.util;
017 
018 import java.awt.Color;
019 import java.awt.Component;
020 import java.awt.Dimension;
021 import java.awt.FlowLayout;
022 import java.awt.Font;
023 import java.awt.Graphics;
024 import java.awt.GridLayout;
025 import java.awt.Rectangle;
026 import java.awt.event.ActionListener;
027 import java.net.URL;
028 
029 import javax.swing.AbstractButton;
030 import javax.swing.BorderFactory;
031 import javax.swing.ImageIcon;
032 import javax.swing.JButton;
033 import javax.swing.JCheckBox;
034 import javax.swing.JComponent;
035 import javax.swing.JPanel;
036 import javax.swing.JRadioButton;
037 import javax.swing.JTable;
038 import javax.swing.JToggleButton;
039 import javax.swing.KeyStroke;
040 import javax.swing.LookAndFeel;
041 import javax.swing.UIManager;
042 import javax.swing.border.Border;
043 import javax.swing.plaf.FontUIResource;
044 import javax.swing.plaf.metal.DefaultMetalTheme;
045 import javax.swing.plaf.metal.MetalLookAndFeel;
046 import javax.swing.table.JTableHeader;
047 import javax.swing.table.TableCellRenderer;
048 import javax.swing.table.TableColumn;
049 import javax.swing.table.TableColumnModel;
050 import javax.swing.table.TableModel;
051 import javax.swing.text.BadLocationException;
052 import javax.swing.text.JTextComponent;
053 
054 import org.qedeq.base.io.ResourceLoaderUtility;
055 import org.qedeq.base.trace.Trace;
056 import org.qedeq.gui.se.main.GuiOptions;
057 
058 import com.jgoodies.looks.Options;
059 import com.jgoodies.looks.plastic.PlasticLookAndFeel;
060 
061 /**
062  * Various GUI utility methods.
063  *
064  @author Michael Meyling
065  */
066 public final class GuiHelper {
067 
068     /** This class. */
069     private static final Class CLASS = GuiHelper.class;
070 
071     /** Color for line highlighter. */
072     private static Color lineHighlighterBackgroundColor = new Color(232242,
073         254);
074 
075     /** Color for line highlighter and marked areas. */
076     private static Color markedAndHiglightedBackgroundColor = new Color(232,
077         242254128);
078 
079     /** Color for error text areas. */
080     private static Color errorTextBackgroundColor = new Color(180206255);
081 
082     /** Color for warning text areas. */
083     private static Color warningTextBackgroundColor = new Color(255255190);
084 
085     /** Width of empty border. */
086     private static final int DEFAULT_EMPTY_BORDER_PIXEL_X = 10;
087 
088     /** Width of empty border. */
089     private static final int DEFAULT_EMPTY_BORDER_PIXEL_Y = 10;
090 
091     /**
092      * Hidden constructor.
093      */
094     private GuiHelper() {
095         // nothing to do
096     }
097 
098     /**
099      * Configures the user interface; requests Swing settings and JGoodies Looks
100      * options from the launcher.
101      *
102      @param   options Set these options.
103      */
104     public static void configureUI(final GuiOptions options) {
105         UIManager.put("ClassLoader", CLASS.getClassLoader());
106 
107         Options.setDefaultIconSize(new Dimension(1818));
108         Options.setUseNarrowButtons(options.isUseNarrowButtons());
109         Options.setTabIconsEnabled(options.isTabIconsEnabled());
110         UIManager.put(Options.POPUP_DROP_SHADOW_ENABLED_KEY, options
111             .isPopupDropShadowEnabled());
112         // LATER m31 20100319: we make this now direct in QedeqPane, this line
113         // didn't help. Why?
114         // we want our disabled TextAreas to look same if not editable
115         UIManager.put("TextArea.disabledBackground", UIManager
116             .get("TextArea.background"));
117 
118         UIManager.put("ToolTip.font",
119                 new FontUIResource("Lucida Sans Unicode", Font.PLAIN,
120                 UIManager.getFont("ToolTip.font").getSize()));
121 
122            // Swing Settings
123         LookAndFeel selectedLaf = options.getSelectedLookAndFeel();
124         if (selectedLaf instanceof PlasticLookAndFeel) {
125             PlasticLookAndFeel.setPlasticTheme(options.getSelectedTheme());
126             PlasticLookAndFeel.setTabStyle(options.getPlasticTabStyle());
127             PlasticLookAndFeel.setHighContrastFocusColorsEnabled(options
128                 .isPlasticHighContrastFocusEnabled());
129         else if (selectedLaf.getClass() == MetalLookAndFeel.class) {
130             MetalLookAndFeel.setCurrentTheme(new DefaultMetalTheme());
131         }
132 
133         // Work around caching in MetalRadioButtonUI
134         JRadioButton radio = new JRadioButton();
135         radio.getUI().uninstallUI(radio);
136         JCheckBox checkBox = new JCheckBox();
137         checkBox.getUI().uninstallUI(checkBox);
138 
139         try {
140             UIManager.setLookAndFeel(selectedLaf);
141         catch (Exception e) {
142             Trace.trace(CLASS, "configureUI""Can't change L&F", e);
143         }
144 
145     }
146 
147     /**
148      * Creates a JButton configured for use in a JToolBar.
149      *
150      @param   iconName    Name of icon.
151      @param   toolTipText Tool tip text.
152      @return  Button.
153      */
154     public static AbstractButton createToolBarButton(final String iconName,
155             final String toolTipText) {
156         final JButton button = new JButton(GuiHelper.readImageIcon(iconName));
157         button.setToolTipText(toolTipText);
158         button.setFocusable(false);
159         return button;
160     }
161 
162     /**
163      * Creates a JButton configured for use in a JToolBar.
164      *
165      @param   iconName    Name of icon.
166      @param   toolTipText Tool tip text.
167      @param   action      Action for this button.
168      @param   keyStroke   Short cut key.
169      @return  Button.
170      */
171     public static AbstractButton createToolBarButton(final String iconName,
172             final String toolTipText, final ActionListener action,
173             final KeyStroke keyStroke) {
174         AbstractButton button = createToolBarButton(iconName, toolTipText);
175         button.registerKeyboardAction(action, keyStroke,
176             JComponent.WHEN_IN_FOCUSED_WINDOW);
177         return button;
178     }
179 
180     /**
181      * Creates a JToggleButton configured for use in a JToolBar.
182      *
183      @param   iconName    Name of icon.
184      @param   toolTipText Tool tip text.
185      @return  Radio button.
186      */
187     public static AbstractButton createToolBarRadioButton(
188             final String iconName, final String toolTipText) {
189         final JToggleButton button = new JToggleButton(GuiHelper
190             .readImageIcon(iconName));
191         button.setToolTipText(toolTipText);
192         button.setFocusable(false);
193         return button;
194     }
195 
196     /**
197      * Get an icon for given filename postfix.
198      *
199      @param   filename    Look for this icon.
200      @return  Icon.
201      */
202     public static ImageIcon readImageIcon(final String filename) {
203         final URL url = ResourceLoaderUtility.getResourceUrl("images/" + filename);
204         if (url == null) {
205             Trace.fatal(CLASS, "readImageIcon""image icon not found: images/" + filename,
206                 new RuntimeException());
207             return null;
208         }
209         return new ImageIcon(url);
210     }
211 
212     /**
213      * Get background color for highlighting the current line.
214      *
215      @return  Background color.
216      */
217     public static Color getLineHighlighterBackgroundColor() {
218         return lineHighlighterBackgroundColor;
219     }
220 
221     /**
222      * Get background color for error text areas.
223      *
224      @return Background color.
225      */
226     public static Color getErrorTextBackgroundColor() {
227         return errorTextBackgroundColor;
228     }
229 
230     /**
231      * Get background color for warning text areas.
232      *
233      @return Background color.
234      */
235     public static Color getWarningTextBackgroundColor() {
236         return warningTextBackgroundColor;
237     }
238 
239     /**
240      * Get background color for marked and highlightted text areas.
241      *
242      @return Background color.
243      */
244     public static Color getCurrentAndMarkedBackgroundColor() {
245         return markedAndHiglightedBackgroundColor;
246     }
247 
248     /**
249      * Paint current line background area with
250      {@link #getLineHighlighterBackgroundColor()}.
251      *
252      @param   g   Graphics to use.
253      @param   c   Text component to work on.
254      @param   col Color to work with.
255      */
256     public static void paintCurrentLineBackground(final Graphics g,
257             final JTextComponent c, final Color col) {
258         // if something is selected we don't highlight
259         if (c.getSelectionStart() != c.getSelectionEnd()) {
260             return;
261         }
262         Rectangle r;
263         try {
264             r = c.modelToView(c.getCaretPosition());
265         catch (BadLocationException couldNotHappen) {
266             throw new RuntimeException(couldNotHappen);
267         }
268         g.setColor(col);
269         g.fillRect(0, r.y, c.getWidth(), r.height);
270     }
271 
272     /**
273      * Adds boarder space and floats panel to the right.
274      *
275      @param   panel   Panel to decorate.
276      @return  Panel with more decorations.
277      */
278     public static JComponent addSpaceAndAlignRight(final JPanel panel) {
279         JPanel withSpace = new JPanel();
280         withSpace.add(panel);
281         JPanel alignRight = new JPanel();
282         alignRight.setLayout(new FlowLayout(FlowLayout.RIGHT));
283         alignRight.add(withSpace);
284         return alignRight;
285     }
286 
287     /**
288      * Width of horizontal empty border.
289      *
290      @return  Return horizontal empty boarder pixel distance.
291      */
292     public static int getEmptyBoderPixelsX() {
293         return DEFAULT_EMPTY_BORDER_PIXEL_X;
294     }
295 
296     /**
297      * Width of vertical empty border.
298      *
299      @return  Return vertical empty boarder pixel distance.
300      */
301     public static int getEmptyBorderPixelsY() {
302         return DEFAULT_EMPTY_BORDER_PIXEL_Y;
303     }
304 
305     /**
306      * A border that puts extra pixels at the sides and bottom of each pane.
307      *
308      @return  Border with extra space.
309      */
310     public static Border getEmptyBorder() {
311         return BorderFactory.createEmptyBorder(GuiHelper
312             .getEmptyBorderPixelsY(), GuiHelper.getEmptyBoderPixelsX(),
313             GuiHelper.getEmptyBorderPixelsY(), GuiHelper.getEmptyBoderPixelsX());
314     }
315 
316     /**
317      * A border that puts extra pixels at the sides and bottom of each pane.
318      *
319      @return  Border with extra space.
320      */
321     public static Border getEmptyBorderStackable() {
322         return BorderFactory.createEmptyBorder(GuiHelper
323             .getEmptyBorderPixelsY() 2, GuiHelper.getEmptyBoderPixelsX(),
324             GuiHelper.getEmptyBorderPixelsY() 2, GuiHelper.getEmptyBoderPixelsX());
325     }
326 
327     /**
328      * Calculate table column width according to contents. See
329      * <a href="http://www.chka.de/swing/table/cell-sizes.html">cell-sizes.html</a>
330      * (calculating initial column widths based on contents).
331      *
332      @author  Christian Kaufhold
333      *
334      @param   table   Calculate width for this table and update column width values.
335      */
336     public static void calcColumnWidths(final JTable table) {
337         final JTableHeader header = table.getTableHeader();
338         TableCellRenderer defaultHeaderRenderer = null;
339         if (header != null) {
340             defaultHeaderRenderer = header.getDefaultRenderer();
341         }
342         TableColumnModel columns = table.getColumnModel();
343         TableModel data = table.getModel();
344         int margin = columns.getColumnMargin()// only JDK1.3
345         int rowCount = data.getRowCount();
346         int totalWidth = 0;
347         for (int i = columns.getColumnCount() 1; i >= 0; --i) {
348             final TableColumn column = columns.getColumn(i);
349             final int columnIndex = column.getModelIndex();
350             int width = -1;
351             TableCellRenderer h = column.getHeaderRenderer();
352             if (h == null) {
353                 h = defaultHeaderRenderer;
354             }
355             if (h != null) { // Not explicitly impossible
356                 Component c = h.getTableCellRendererComponent(table, column.getHeaderValue(),
357                     false, false, -1, i);
358                 width = c.getPreferredSize().width;
359             }
360             for (int row = rowCount - 1; row >= 0; --row) {
361                 TableCellRenderer r = table.getCellRenderer(row, i);
362                 Component c = r.getTableCellRendererComponent(table, data.getValueAt(row,
363                     columnIndex), false, false, row, i);
364                 width = Math.max(width, c.getPreferredSize().width);
365             }
366             if (width >= 0) {
367                 column.setPreferredWidth(width + margin);
368             else {
369                 // ???
370             }
371             totalWidth += column.getPreferredWidth();
372         }
373     }
374 
375     public static JComponent addSpaceAndTitle(final JPanel panel, final String title) {
376         JPanel withSpace = new JPanel();
377         withSpace.setBorder(getEmptyBorderStackable());
378         withSpace.add(panel);
379         withSpace.setLayout(new GridLayout(01));
380         JPanel withTitle = new JPanel();
381         withTitle.setBorder(BorderFactory.createTitledBorder(title));
382         withTitle.add(withSpace);
383         withTitle.setLayout(new GridLayout(01));
384         return withTitle;
385     }
386 
387 }