1 19 20 package org.openide.awt; 21 22 import java.awt.Component ; 23 import java.util.ArrayList ; 24 import java.util.Arrays ; 25 import java.util.Collections ; 26 import java.util.HashMap ; 27 import java.util.Iterator ; 28 import java.util.List ; 29 import java.util.Map ; 30 import javax.swing.Action ; 31 import javax.swing.Icon ; 32 import javax.swing.ImageIcon ; 33 import javax.swing.JComponent ; 34 import javax.swing.JMenu ; 35 import javax.swing.JMenuItem ; 36 import javax.swing.JPopupMenu ; 37 import javax.swing.JSeparator ; 38 import org.openide.util.Utilities; 39 import org.openide.awt.DynamicMenuContent; 40 import org.openide.util.actions.Presenter; 41 42 46 class DynaMenuModel { 47 private static final Icon BLANK_ICON = new ImageIcon ( 48 Utilities.loadImage("org/openide/loaders/empty.gif")); 50 private List <JComponent > menuItems; 51 private HashMap <DynamicMenuContent, JComponent []> actionToMenuMap; 52 private boolean isWithIcons = false; 53 54 public DynaMenuModel() { 55 actionToMenuMap = new HashMap <DynamicMenuContent, JComponent []>(); 56 } 57 58 public void loadSubmenu(List cInstances, JMenu m) { 59 boolean addSeparator = false; 61 Icon curIcon = null; 62 Iterator it = cInstances.iterator(); 63 menuItems = new ArrayList <JComponent >(cInstances.size()); 64 actionToMenuMap.clear(); 65 while (it.hasNext()) { 66 Object obj = it.next(); 67 if (obj instanceof Presenter.Menu) { 68 obj = ((Presenter.Menu)obj).getMenuPresenter(); 70 } 71 if (obj instanceof DynamicMenuContent) { 72 if(addSeparator) { 73 menuItems.add(null); 74 addSeparator = false; 75 } 76 DynamicMenuContent mn = (DynamicMenuContent)obj; 77 JComponent [] itms = convertArray(mn.getMenuPresenters()); 78 actionToMenuMap.put(mn, itms); 79 Iterator itx = Arrays.asList(itms).iterator(); 80 while (itx.hasNext()) { 81 JComponent comp = (JComponent )itx.next(); 82 menuItems.add(comp); 83 isWithIcons = checkIcon(comp, isWithIcons); 85 } 86 continue; 87 } 88 89 90 if (obj instanceof JMenuItem ) { 91 if(addSeparator) { 92 menuItems.add(null); 93 addSeparator = false; 94 } 95 isWithIcons = checkIcon(obj, isWithIcons); 97 menuItems.add((JMenuItem )obj); 98 } else if (obj instanceof JSeparator ) { 99 addSeparator = menuItems.size() > 0; 100 } else if (obj instanceof Action ) { 101 if(addSeparator) { 102 menuItems.add(null); 103 addSeparator = false; 104 } 105 Action a = (Action )obj; 106 Actions.MenuItem item = new Actions.MenuItem(a, true); 107 isWithIcons = checkIcon(item, isWithIcons); 109 actionToMenuMap.put(item, new JComponent [] {item}); 110 menuItems.add(item); 111 } 112 } 113 114 if (isWithIcons) { 115 menuItems = alignVertically(menuItems); 116 } 117 118 JComponent curItem = null; 120 boolean wasSeparator = false; 121 for (Iterator <JComponent > iter = menuItems.iterator(); iter.hasNext(); ) { 122 curItem = iter.next(); 123 if (curItem == null) { 124 curItem = new JSeparator (); 126 } 127 m.add(curItem); 128 boolean isSeparator = curItem instanceof JSeparator ; 129 if (isSeparator && wasSeparator) { 130 curItem.setVisible(false); 131 } 132 if (!(curItem instanceof InvisibleMenuItem)) { 133 wasSeparator = isSeparator; 134 } 135 } 136 } 137 138 139 private boolean checkIcon(Object obj, boolean isWithIconsAlready) { 140 if (isWithIconsAlready) { 141 return isWithIconsAlready; 142 } 143 if (obj instanceof JMenuItem ) { 144 if (((JMenuItem )obj).getIcon() != null && !BLANK_ICON.equals(((JMenuItem )obj).getIcon())) { 145 return true; 146 } 147 } 148 return false; 149 } 150 151 public void checkSubmenu(JMenu menu) { 152 boolean oldisWithIcons = isWithIcons; 153 boolean changed = false; 154 for (Map.Entry <DynamicMenuContent, JComponent []> entry: actionToMenuMap.entrySet()) { 155 DynamicMenuContent pres = entry.getKey(); 156 JComponent [] old = entry.getValue(); 157 int oldIndex = 0; 158 Component [] menuones = menu.getPopupMenu().getComponents(); 159 int menuIndex = old.length > 0 ? findFirstItemIndex(old[0], menuones) : -1; 160 JComponent [] newones = convertArray(pres.synchMenuPresenters(unconvertArray(old))); 161 if (!compareEqualArrays(old, newones)) { 162 if (menuIndex < 0) { 163 menuIndex = 0; 164 } else { 165 for (int i = 0; i < old.length; i++) { 166 if (old[i] != null) { 167 menu.getPopupMenu().remove(old[i]); 168 menuItems.remove(old[i]); 169 } 170 } 171 } 172 for (int i = 0; i < newones.length; i++) { 173 JComponent one = newones[i]; 175 menu.getPopupMenu().add(one, i + menuIndex); 176 changed = true; 177 menuItems.add(one); 178 boolean thisOneHasIcon = checkIcon(one, false); 179 if (!thisOneHasIcon && isWithIcons) { 180 alignVertically(Collections.singletonList(one)); 181 } 182 if (thisOneHasIcon && !isWithIcons) { 183 isWithIcons = true; 184 } 185 } 186 entry.setValue(newones); 187 } 188 189 } 190 boolean hasAnyIcons = false; 191 Component [] menuones = menu.getPopupMenu().getComponents(); 192 for (int i = 0; i < menuones.length; i++) { 193 if (menuones[i] != null) { 194 hasAnyIcons = checkIcon(menuones[i], hasAnyIcons); 195 if (hasAnyIcons) { 196 break; 197 } 198 } 199 } 200 checkSeparators(menuones, menu.getPopupMenu()); 201 if (!hasAnyIcons && isWithIcons) { 202 isWithIcons = false; 203 } 204 if (oldisWithIcons != isWithIcons) { 205 menuItems = alignVertically(menuItems); 206 } 207 if (changed && Utilities.isWindows()) { 208 menu.getPopupMenu().revalidate(); 210 } 211 } 212 213 static void checkSeparators(Component [] menuones, JPopupMenu parent) { 214 boolean wasSeparator = false; 215 for (int i = 0; i < menuones.length; i++) { 216 Component curItem = menuones[i]; 217 if (curItem != null) { 218 boolean isSeparator = curItem instanceof JSeparator ; 219 if (isSeparator) { 220 boolean isVisible = curItem.isVisible(); 221 if (isVisible != !wasSeparator) { 222 parent.remove(i); 225 JSeparator newOne = new JSeparator (); 226 newOne.setVisible(!wasSeparator); 227 parent.add(newOne, i); 228 } 229 } 230 if (!(curItem instanceof InvisibleMenuItem)) { 231 wasSeparator = isSeparator; 232 } 233 } 234 } 235 } 236 237 private JComponent [] convertArray(JComponent [] arr) { 238 if (arr == null || arr.length == 0) { 239 return new JComponent [] { new InvisibleMenuItem() }; 240 } 241 JComponent [] toRet = new JComponent [arr.length]; 242 for (int i = 0; i < arr.length; i++) { 243 if (arr[i] == null) { 244 toRet[i] = new JSeparator (); 245 } else { 246 toRet[i] = arr[i]; 247 } 248 } 249 return toRet; 250 } 251 252 private JComponent [] unconvertArray(JComponent [] arr) { 253 if (arr.length == 1 && arr[0] instanceof InvisibleMenuItem) { 254 return new JComponent [0]; 255 } else { 256 return arr; 257 } 258 } 259 260 private int findFirstItemIndex(JComponent first, Component [] menuItems) { 261 for (int i = 0; i < menuItems.length; i++) { 262 if (first == menuItems[i]) { 263 return i; 264 } 265 } 266 return -1; 267 } 268 269 private boolean compareEqualArrays(JComponent [] one, JComponent [] two) { 270 if (one.length != two.length) { 271 return false; 272 } 273 for (int i = 0; i < one.length; i++) { 274 if (one[i] != two[i]) { 275 return false; 276 } 277 } 278 return true; 279 } 280 281 283 private List <JComponent > alignVertically(List <JComponent > menuItems) { 284 List <JComponent > result = new ArrayList <JComponent >(menuItems.size()); 285 JMenuItem curItem = null; 286 for (JComponent obj: menuItems) { 287 if (obj instanceof JMenuItem ) { 288 curItem = (JMenuItem )obj; 289 if (isWithIcons && curItem != null && curItem.getIcon() == null) { 290 curItem.setIcon(BLANK_ICON); 291 } else if (!isWithIcons && curItem != null) { 292 curItem.setIcon(null); 293 } 294 } 295 result.add(obj); 296 } 297 return result; 298 } 299 300 static final class InvisibleMenuItem extends JMenuItem { 301 302 public boolean isVisible() { 303 return false; 304 } 305 306 } 307 } 308 | Popular Tags |