Home | History | Annotate | Download | only in presentation
      1 /*******************************************************************************
      2  * Copyright (c) 2011 Google, Inc.
      3  * All rights reserved. This program and the accompanying materials
      4  * are made available under the terms of the Eclipse Public License v1.0
      5  * which accompanies this distribution, and is available at
      6  * http://www.eclipse.org/legal/epl-v10.html
      7  *
      8  * Contributors:
      9  *    Google, Inc. - initial API and implementation
     10  *******************************************************************************/
     11 package org.eclipse.wb.internal.core.model.property.editor.presentation;
     12 
     13 import com.google.common.collect.Maps;
     14 
     15 import org.eclipse.swt.SWT;
     16 import org.eclipse.swt.graphics.Rectangle;
     17 import org.eclipse.swt.widgets.Button;
     18 import org.eclipse.swt.widgets.Control;
     19 import org.eclipse.swt.widgets.Event;
     20 import org.eclipse.swt.widgets.Listener;
     21 import org.eclipse.wb.internal.core.model.property.Property;
     22 import org.eclipse.wb.internal.core.model.property.table.PropertyTable;
     23 import org.eclipse.wb.internal.core.utils.Pair;
     24 
     25 import java.util.Map;
     26 
     27 /**
     28  * Internal implementation of {@link PropertyEditorPresentation} for displaying {@link Button}.
     29  *
     30  * @author scheglov_ke
     31  * @author mitin_aa
     32  * @coverage core.model.property.editor
     33  */
     34 class ButtonPropertyEditorPresentationImpl extends PropertyEditorPresentation {
     35   protected final PropertyToControlMap m_propertyToControl = new PropertyToControlMap();
     36   private final ButtonPropertyEditorPresentation m_presentation;
     37 
     38   ////////////////////////////////////////////////////////////////////////////
     39   //
     40   // Constructor
     41   //
     42   ////////////////////////////////////////////////////////////////////////////
     43   public ButtonPropertyEditorPresentationImpl(ButtonPropertyEditorPresentation presentation) {
     44     m_presentation = presentation;
     45   }
     46 
     47   ////////////////////////////////////////////////////////////////////////////
     48   //
     49   // PropertyEditorPresentation
     50   //
     51   ////////////////////////////////////////////////////////////////////////////
     52   @Override
     53   public final void hide(PropertyTable propertyTable, Property property) {
     54     Control control = m_propertyToControl.remove(propertyTable, property);
     55     if (control != null) {
     56       control.dispose();
     57     }
     58   }
     59 
     60   @Override
     61   public final int show(PropertyTable propertyTable,
     62       Property property,
     63       int x,
     64       int y,
     65       int width,
     66       int height) {
     67     // prepare control
     68     Control control = m_propertyToControl.get(propertyTable, property);
     69     if (control == null) {
     70       control = createControl(propertyTable, property);
     71     }
     72     // set bounds
     73     final int controlWidth = height;
     74     final int controlX = x + width - controlWidth;
     75     setBounds(control, controlX, y, controlWidth, height);
     76     return controlWidth;
     77   }
     78 
     79   /**
     80    * Finds and select the appropriate {@link Control} belonging to given property.
     81    */
     82   public void setSelection(PropertyTable propertyTable, Property property, boolean selected) {
     83     Button button = (Button) m_propertyToControl.get(propertyTable, property);
     84     if (button != null) {
     85       button.setSelection(selected);
     86     }
     87   }
     88 
     89   ////////////////////////////////////////////////////////////////////////////
     90   //
     91   // Control
     92   //
     93   ////////////////////////////////////////////////////////////////////////////
     94   /**
     95    * Creates the control for given property and initializes newly created control.
     96    */
     97   private Control createControl(final PropertyTable propertyTable, final Property property) {
     98     Control control = createControlImpl(propertyTable, property);
     99     m_propertyToControl.put(propertyTable, property, control);
    100     // when Control disposed, remove Control/Property from map to avoid memory leak
    101     control.addListener(SWT.Dispose, new Listener() {
    102       @Override
    103     public void handleEvent(Event e) {
    104         m_propertyToControl.remove(propertyTable, property);
    105       }
    106     });
    107     // activate property on mouse down
    108     control.addListener(SWT.MouseDown, new Listener() {
    109       @Override
    110     public void handleEvent(Event event) {
    111         propertyTable.deactivateEditor(true);
    112         propertyTable.setActiveProperty(property);
    113       }
    114     });
    115     // return focus on propertyTable after click
    116     control.addListener(SWT.MouseUp, new Listener() {
    117       @Override
    118     public void handleEvent(Event event) {
    119         propertyTable.forceFocus();
    120       }
    121     });
    122     // handle selection
    123     control.addListener(SWT.Selection, new Listener() {
    124       @Override
    125     public void handleEvent(Event event) {
    126         try {
    127           getPresentation().onClick(propertyTable, property);
    128         } catch (Throwable e) {
    129           propertyTable.deactivateEditor(false);
    130           propertyTable.handleException(e);
    131         }
    132       }
    133     });
    134     return control;
    135   }
    136 
    137   /**
    138    * Creates the {@link Control} instance. By default, {@link Button} instance created.
    139    */
    140   protected Control createControlImpl(final PropertyTable propertyTable, final Property property) {
    141     Button button = new Button(propertyTable, getPresentation().getStyle());
    142     button.setImage(getPresentation().getImage());
    143     button.setToolTipText(getPresentation().getTooltip());
    144     return button;
    145   }
    146 
    147   ////////////////////////////////////////////////////////////////////////////
    148   //
    149   // Access
    150   //
    151   ////////////////////////////////////////////////////////////////////////////
    152   /**
    153    * @return the 'parent' presentation. Internal usage only.
    154    */
    155   protected final ButtonPropertyEditorPresentation getPresentation() {
    156     return m_presentation;
    157   }
    158 
    159   ////////////////////////////////////////////////////////////////////////////
    160   //
    161   // Utils
    162   //
    163   ////////////////////////////////////////////////////////////////////////////
    164   /**
    165    * Sets new bounds for {@link Control}, optimizing when possible.
    166    */
    167   private static void setBounds(Control control, int newX, int newY, int newWidth, int newHeight) {
    168     // check, may be Control is invisible, so no reason to change bounds
    169     {
    170       // is in negative zone
    171       if (newY + newHeight < 0) {
    172         control.setVisible(false);
    173         return;
    174       }
    175       // is out of client area height
    176       Rectangle parentArea = control.getParent().getClientArea();
    177       if (newY > parentArea.height) {
    178         control.setVisible(false);
    179         return;
    180       }
    181     }
    182     // well, now we sure that Control is visible
    183     if (!control.getVisible()) {
    184       control.setVisible(true);
    185     }
    186     // prepare old size, remember new
    187     Integer oldWidthObject = (Integer) control.getData("oldWidth");
    188     Integer oldHeightObject = (Integer) control.getData("oldHeight");
    189     control.setData("oldWidth", newWidth);
    190     control.setData("oldHeight", newHeight);
    191     // check, may be same size
    192     if (oldWidthObject != null) {
    193       int oldWidth = oldWidthObject.intValue();
    194       int oldHeight = oldHeightObject.intValue();
    195       if (oldWidth == newWidth && oldHeight == newHeight) {
    196         control.setLocation(newX, newY);
    197         return;
    198       }
    199     }
    200     // no any optimization possible, just set bounds
    201     control.setBounds(newX, newY, newWidth, newHeight);
    202   }
    203 
    204   ////////////////////////////////////////////////////////////////////////////
    205   //
    206   // Controls map
    207   //
    208   ////////////////////////////////////////////////////////////////////////////
    209   protected static final class PropertyToControlMap {
    210     private final Map<Pair<PropertyTable, Property>, Control> m_map = Maps.newHashMap();
    211 
    212     void put(PropertyTable propertyTable, Property property, Control control) {
    213       m_map.put(Pair.create(propertyTable, property), control);
    214     }
    215 
    216     Control remove(PropertyTable propertyTable, Property property) {
    217       return m_map.remove(Pair.create(propertyTable, property));
    218     }
    219 
    220     Control get(PropertyTable propertyTable, Property property) {
    221       return m_map.get(Pair.create(propertyTable, property));
    222     }
    223   }
    224 }
    225