/**************************************************************************** * Copyright (c) 2008, 2009 Jeremy Dowdall * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jeremy Dowdall <jeremyd@aspencloud.com> - initial API and implementation *****************************************************************************/ package org.eclipse.nebula.cwt.v; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; class VButtonImageBak { private class ImageListener implements Listener { private String key; private Button b; ImageListener(String key, Button b) { this.key = key; this.b = b; } public void handleEvent(Event e) { GC gc = new GC(b); Image image = new Image(b.getDisplay(), e.width, e.height); gc.copyArea(image, 0, 0); ImageData data = image.getImageData(); gc.dispose(); image.dispose(); images.put(key, data); keys.put(data, key); if(requests.containsKey(key)) { for(Iterator<VButton> iter = requests.get(key).iterator(); iter.hasNext();) { iter.next().redraw(); iter.remove(); } requests.remove(key); } Display.getDefault().asyncExec(new Runnable() { public void run() { if(!b.isDisposed() && b == b.getDisplay().getFocusControl()) { b.getParent().forceFocus(); } b.dispose(); } }); } } private static VButtonImageBak instance; private static String getKey(VButton button) { StringBuilder sb = new StringBuilder(); sb.append(button.getState()); sb.append(button == VTracker.getFocusControl()); sb.append(":"); //$NON-NLS-1$ sb.append(button.bounds.width); sb.append(":"); //$NON-NLS-1$ sb.append(button.bounds.height); return sb.toString(); } public static VButtonImageBak instance() { if(instance == null) { instance = new VButtonImageBak(); } return instance; } /** * Maps a unique key to a single image data object. Key => {state} : {width} : * {height} */ private Map<String, ImageData> images = new HashMap<String, ImageData>(); /** * Map an image data object back to its unique key. */ private Map<ImageData, String> keys = new HashMap<ImageData, String>(); /** * Maps a unique key to a list of buttons who have requested an image data * object for that key. */ private Map<String, List<VButton>> requests = new HashMap<String, List<VButton>>(); /** * Maps an image data object to the set of buttons that use that image data * object. */ private Map<ImageData, Set<VButton>> buttons = new HashMap<ImageData, Set<VButton>>(); private VButtonImageBak() { // } private void createImage(VButton button) { String key = getKey(button); if(requests.containsKey(key)) { requests.get(key).add(button); } else { requests.put(key, new ArrayList<VButton>()); requests.get(key).add(button); int style = button.getStyle() & (SWT.CHECK | SWT.RADIO); if(style == 0) { style = SWT.TOGGLE; // defaults to, and converts PUSH buttons to, TOGGLE } Button b = new Button(button.composite, style); b.setBackground(button.getBackground()); b.setBounds(button.getBounds()); if(button.hasState(VControl.STATE_SELECTED)) { b.setSelection(true); } if(button == VTracker.getFocusControl()) { b.setFocus(); } b.addListener(SWT.Paint, new ImageListener(key, b)); b.redraw(); b.update(); } } public ImageData getImageData(VButton button) { if(!button.bounds.isEmpty()) { String key = getKey(button); ImageData data = images.get(key); if(data == null) { createImage(button); } else { if(partialImage(key, data)) { images.remove(key); keys.remove(data); } else { if(button.oldImageData != null && button.oldImageData != data) { removeUnusedData(); } if(!buttons.containsKey(data)) { buttons.put(data, new HashSet<VButton>()); } if(!buttons.get(data).contains(button)) { buttons.get(data).add(button); } } return data; } } return null; } private boolean partialImage(String key, ImageData data) { String[] sa = key.split(":"); //$NON-NLS-1$ int w = Integer.parseInt(sa[1]); int h = Integer.parseInt(sa[2]); return (data.height != h) || (data.width != w); } void removeUnusedData() { for(Iterator<ImageData> i1 = buttons.keySet().iterator(); i1.hasNext();) { ImageData data = i1.next(); for(Iterator<VButton> i2 = buttons.get(data).iterator(); i2.hasNext();) { Point size = i2.next().getSize(); if(size.x != data.width || size.y != data.height) { i2.remove(); } } if(buttons.get(data).isEmpty()) { images.remove(keys.get(data)); keys.remove(data); i1.remove(); } } } }