1 /* 2 * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package build.tools.generatenimbus; 27 28 import javax.xml.stream.XMLStreamException; 29 import javax.xml.stream.XMLStreamReader; 30 import java.util.ArrayList; 31 import java.util.List; 32 import java.util.Map; 33 34 class UIRegion { 35 String name; 36 String key; 37 private boolean opaque = false; 38 39 private Insets contentMargins = new Insets(0, 0, 0, 0); 40 41 protected List<UIState> backgroundStates = new ArrayList<UIState>(); 42 43 public List<UIState> getBackgroundStates() { return backgroundStates; } 44 45 protected List<UIState> foregroundStates = new ArrayList<UIState>(); 46 public List<UIState> getForegroundStates() { return foregroundStates; } 47 48 protected List<UIState> borderStates = new ArrayList<UIState>(); 49 public List<UIState> getBorderStates() { return borderStates; } 50 51 UIStyle style = new UIStyle(); 52 53 List<UIRegion> subRegions = new ArrayList<>(); 54 public List<UIRegion> getSubRegions() { return subRegions; } 55 56 UIRegion(XMLStreamReader reader, boolean parse) 57 throws XMLStreamException { 58 name = reader.getAttributeValue(null, "name"); 59 key = reader.getAttributeValue(null, "key"); 60 opaque = Boolean.parseBoolean(reader.getAttributeValue(null, "opaque")); 61 if (!parse) { 62 return; 63 } 64 while (reader.hasNext()) { 65 int eventType = reader.next(); 66 switch (eventType) { 67 case XMLStreamReader.START_ELEMENT: 68 parse(reader); 69 break; 70 case XMLStreamReader.END_ELEMENT: 71 switch (reader.getLocalName()) { 72 case "region": 73 return; 74 } 75 break; 76 } 77 } 78 } 79 80 private List<UIState> states = new ArrayList<UIState>(); 81 82 void parse(XMLStreamReader reader) throws XMLStreamException { 83 switch (reader.getLocalName()) { 84 case "backgroundStates": 85 backgroundStates = states = new ArrayList<>(); 86 break; 87 case "foregroundStates": 88 foregroundStates = states = new ArrayList<>(); 89 break; 90 case "borderStates": 91 borderStates = states = new ArrayList<>(); 92 break; 93 case "style": 94 style = new UIStyle(reader); 95 break; 96 case "region": 97 subRegions.add(new UIRegion(reader, true)); 98 break; 99 case "uiComponent": 100 subRegions.add(new UIComponent(reader)); 101 break; 102 case "uiIconRegion": 103 subRegions.add(new UIIconRegion(reader)); 104 break; 105 case "contentMargins": 106 contentMargins = new Insets(reader); 107 break; 108 case "state": 109 states.add(new UIState(reader)); 110 break; 111 } 112 } 113 114 protected void initStyles(UIStyle parentStyle) { 115 style.setParentStyle(parentStyle); 116 for (UIState state: backgroundStates) { 117 state.getStyle().setParentStyle(this.style); 118 } 119 for (UIState state: foregroundStates) { 120 state.getStyle().setParentStyle(this.style); 121 } 122 for (UIState state: borderStates) { 123 state.getStyle().setParentStyle(this.style); 124 } 125 for (UIRegion region: subRegions) { 126 region.initStyles(this.style); 127 } 128 } 129 130 public String getKey() { 131 return key == null || "".equals(key) ? name : key; 132 } 133 134 private boolean hasCanvas() { 135 for (UIState s : backgroundStates) { 136 if (s.hasCanvas()) return true; 137 } 138 for (UIState s : borderStates) { 139 if (s.hasCanvas()) return true; 140 } 141 for (UIState s : foregroundStates) { 142 if (s.hasCanvas()) return true; 143 } 144 for (UIRegion r: subRegions) { 145 if (r.hasCanvas()) return true; 146 } 147 return false; 148 } 149 150 public void write(StringBuilder sb, StringBuilder styleBuffer, 151 UIComponent comp, String prefix, String pkg) { 152 // write content margins 153 sb.append(String.format(" d.put(\"%s.contentMargins\", %s);\n", 154 prefix, contentMargins.write(true))); 155 // write opaque if true 156 if (opaque) { 157 sb.append(String.format(" d.put(\"%s.opaque\", Boolean.TRUE);\n", prefix)); 158 } 159 160 // register component with LAF 161 String regionCode = "Region." + Utils.regionNameToCaps(name); 162 styleBuffer.append(String.format(" register(%s, \"%s\");\n", 163 regionCode, prefix)); 164 165 //write the State, if necessary 166 StringBuffer regString = new StringBuffer(); 167 List<UIStateType> types = comp.getStateTypes(); 168 if (types != null && types.size() > 0) { 169 for (UIStateType type : types) { 170 regString.append(type.getKey()); 171 regString.append(","); 172 } 173 //remove the last "," 174 regString.deleteCharAt(regString.length() - 1); 175 } 176 177 if (! regString.equals("Enabled,MouseOver,Pressed,Disabled,Focused,Selected,Default") && types.size() > 0) { 178 //there were either custom states, or the normal states were in a custom order 179 //so go ahead and write out prefix.State 180 sb.append(String.format(" d.put(\"%s.States\", \"%s\");\n", 181 prefix, regString)); 182 } 183 184 // write out any custom states, if necessary 185 for (UIStateType type : types) { 186 String synthState = type.getKey(); 187 if (! "Enabled".equals(synthState) && 188 ! "MouseOver".equals(synthState) && 189 ! "Pressed".equals(synthState) && 190 ! "Disabled".equals(synthState) && 191 ! "Focused".equals(synthState) && 192 ! "Selected".equals(synthState) && 193 ! "Default".equals(synthState)) { 194 195 //what we have here, gentlemen, is a bona-fide custom state. 196 //if the type is not one of the standard types, then construct a name for 197 //the new type, and write out a new subclass of State. 198 String className = Utils.normalize(prefix) + synthState + "State"; 199 sb.append(String.format(" d.put(\"%s.%s\", new %s());\n", 200 prefix, synthState, className)); 201 202 String body = type.getCodeSnippet(); 203 Map<String, String> variables = Generator.getVariables(); 204 variables.put("STATE_NAME", className); 205 variables.put("STATE_KEY", synthState); 206 variables.put("BODY", body); 207 208 Generator.writeSrcFile("StateImpl", variables, className); 209 } 210 } 211 212 // write style 213 sb.append(style.write(prefix + '.')); 214 215 String fileName = Utils.normalize(prefix) + "Painter"; 216 boolean hasCanvas = hasCanvas(); 217 if (hasCanvas) { 218 PainterGenerator.writePainter(this, fileName); 219 } 220 // write states ui defaults 221 for (UIState state : backgroundStates) { 222 state.write(sb, prefix, pkg, fileName, "background"); 223 } 224 for (UIState state : foregroundStates) { 225 state.write(sb, prefix, pkg, fileName, "foreground"); 226 } 227 for (UIState state : borderStates) { 228 state.write(sb, prefix, pkg, fileName, "border"); 229 } 230 231 // handle sub regions 232 for (UIRegion subreg : subRegions) { 233 String p = prefix; 234 if (! (subreg instanceof UIIconRegion)) { 235 p = prefix + ":" + Utils.escape(subreg.getKey()); 236 } 237 UIComponent c = comp; 238 if (subreg instanceof UIComponent) { 239 c = (UIComponent) subreg; 240 } 241 subreg.write(sb, styleBuffer, c, p, pkg); 242 } 243 } 244 }