r23229 - Switch skins without restart => new FSkin API

It took longer than I had hoped, but I finally finished the major refactoring of skin support I've been working on that allows changing skins without restarting. It wasn't easy, but I think it makes the Theme/Skin support for Forge much nicer to use, and will hopefully encourage more skins to be created.
See below for details on the new implementation of this logic.
All developers should be aware that the way to use the FSkin class has changed. There are still getColor(), getFont(), getImage, and getIcon() functions for accessing skin-based properties, but they now return objects of type SkinColor, SkinFont, SkinImage, and SkinIcon respectively. I also added a getCursor() function and corresponding SkinCursor class for custom cursors. These Skin* objects should then be passed to a function with more or less the same name as the one you would have normally called, but rather than being on the component, it will be on an instance of ComponentSkin<T extends Component>, which is another new class that wraps all Skin* properties set for a given component such that they can be reapplied when switching skins.
To access the ComponentSkin object for a given component, simply call FSkin.get(comp). ComponentSkin has several subclasses (each with the name "<component class>Skin"), each with functions unique to a given component and any components extending that component, but FSkin.get(comp) will automatically return an instance of the one that fits it best, giving you access to all the functions you might need.
Below is a full list of available functions and examples for setting skin-based properties on different types of components. Please note that although I use FSkin.get on each line, it should probably be cached in a variable if it needs to be used more than once to save the performance of multiple HashMap accesses. Similar with caching Skin* objects retrieved from their associated functions if the same object would be used multiple times.
I did my best to keep these changes as minimal as possible, and ultimately I'm confident I found the best way without requiring far more extensive rewriting of the GUI code. I hope adjusting to these API changes will go smoothly for everyone involved, and please let me know if you have any questions or concerns. Also, if you can in the next several days, please try to check that skins are applied correctly on all views both when first starting Forge and after changing the skin, just in case I missed any screens or views in my own testing.
Thanks.
-Dan
See below for details on the new implementation of this logic.
To access the ComponentSkin object for a given component, simply call FSkin.get(comp). ComponentSkin has several subclasses (each with the name "<component class>Skin"), each with functions unique to a given component and any components extending that component, but FSkin.get(comp) will automatically return an instance of the one that fits it best, giving you access to all the functions you might need.
Below is a full list of available functions and examples for setting skin-based properties on different types of components. Please note that although I use FSkin.get on each line, it should probably be cached in a variable if it needs to be used more than once to save the performance of multiple HashMap accesses. Similar with caching Skin* objects retrieved from their associated functions if the same object would be used multiple times.
- Code: Select all
/*ComponentSkin<T extends Component>*/
FSkin.get(comp).setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
FSkin.get(comp).setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME));
FSkin.get(comp).setFont(FSkin.getFont(12));
FSkin.get(comp).setCursor(FSkin.getCursor(FSkin.LayoutImages.IMG_CUR_L, 16, 16, "CUR_L"));
FSkin.get(comp).setGraphicsColor(g, FSkin.getColor(FSkin.Colors.CLR_THEME));
FSkin.get(comp).setGraphicsGradientPaint(g2d, x1, y1, FSkin.getColor(FSkin.Colors.CLR_THEME), x2, y2, FSkin.getColor(FSkin.Colors.CLR_THEME).stepColor(30));
FSkin.get(comp).drawImage(g, FSkin.getImage(FSkin.ColorlessManaImages.IMG_0, 16, 16), x1, y1);
/*JFrameSkin<T extends JFrame> extends ComponentSkin<T>*/
FSkin.get(comp).setIconImage(FSkin.getIcon(FSkin.InterfaceIcons.ICO_FAVICON));
/*JComponentSkin<T extends JComponent> extends ComponentSkin<T>*/
FSkin.get(comp).setLineBorder(FSkin.getColor(FSkin.Colors.CLR_BORDERS));
FSkin.get(comp).setMatteBorder(top, left, bottom, right, FSkin.getColor(FSkin.Colors.CLR_TEXT));
/*JLabelSkin<T extends JLabel> extends JComponentSkin<T>*/
FSkin.get(comp).setIcon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_FLIPCARD));
/*AbstractButtonSkin<T extends AbstractButton> extends JComponentSkin<T>*/
FSkin.get(comp).setIcon(FSkin.getIcon(FSkin.ButtonImages.IMG_BTN_START_UP));
FSkin.get(comp).setPressedIcon(FSkin.getIcon(FSkin.ButtonImages.IMG_BTN_START_DOWN));
FSkin.get(comp).setRolloverIcon(FSkin.getIcon(FSkin.ButtonImages.IMG_BTN_START_OVER));
/*JTextComponentSkin<T extends JTextComponent> extends JComponentSkin<T>*/
FSkin.get(comp).setCaretColor(FSkin.getColor(FSkin.Colors.CLR_TEXT));
/*JTableSkin<T extends JTable> extends JComponentSkin<T>*/
FSkin.get(comp).setSelectionForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
FSkin.get(comp).setSelectionBackground(FSkin.getColor(FSkin.Colors.CLR_INACTIVE));
/*FPanelSkin<T extends FPanel> extends JComponentSkin<T>*/
FSkin.get(comp).setForegroundImage(FSkin.getIcon(FSkin.Backgrounds.BG_MATCH));
FSkin.get(comp).setBackgroundTexture(FSkin.getIcon(FSkin.Backgrounds.BG_TEXTURE));
I did my best to keep these changes as minimal as possible, and ultimately I'm confident I found the best way without requiring far more extensive rewriting of the GUI code. I hope adjusting to these API changes will go smoothly for everyone involved, and please let me know if you have any questions or concerns. Also, if you can in the next several days, please try to check that skins are applied correctly on all views both when first starting Forge and after changing the skin, just in case I missed any screens or views in my own testing.
Thanks.
-Dan