001package org.vishia.gral.swt;
002
003import org.eclipse.swt.SWT;
004import org.eclipse.swt.events.PaintEvent;
005import org.eclipse.swt.events.PaintListener;
006import org.eclipse.swt.events.TraverseEvent;
007import org.eclipse.swt.events.TraverseListener;
008import org.eclipse.swt.graphics.Color;
009import org.eclipse.swt.graphics.Font;
010import org.eclipse.swt.graphics.FontMetrics;
011import org.eclipse.swt.graphics.GC;
012import org.eclipse.swt.graphics.Rectangle;
013import org.eclipse.swt.widgets.Canvas;
014import org.eclipse.swt.widgets.Composite;
015import org.eclipse.swt.widgets.Control;
016import org.eclipse.swt.widgets.Widget;
017import org.vishia.gral.base.GralButton;
018import org.vishia.gral.base.GralKeyListener;
019import org.vishia.gral.base.GralPos;
020import org.vishia.gral.base.GralWidget;
021import org.vishia.gral.ifc.GralColor;
022import org.vishia.gral.ifc.GralRectangle;
023import org.vishia.gral.ifc.GralWidget_ifc;
024import org.vishia.util.KeyCode;
025
026public class SwtButton extends GralButton.GraphicImplAccess
027{
028  /**Version, history and license.
029   * <ul>
030   * <li>2013-12-22 Hartmut chg: Now {@link GralButton} uses the new concept of instantiation: It is not
031   *   the super class of the implementation class. But it provides {@link GralButton.GraphicImplAccess}
032   *   as the super class. 
033   * <li>2012-03-09 Hartmut new setFocus on press button
034   * <li>2012-03-09 Hartmut new 3-state-Button.
035   * <li>2012-03-09 Hartmut improved: appearance of the buttons.
036   * <li>All other changes in 2010, 2011
037   * </ul>
038   * 
039   * <b>Copyright/Copyleft</b>:<br>
040   * For this source the LGPL Lesser General Public License,
041   * published by the Free Software Foundation is valid.
042   * It means:
043   * <ol>
044   * <li> You can use this source without any restriction for any desired purpose.
045   * <li> You can redistribute copies of this source to everybody.
046   * <li> Every user of this source, also the user of redistribute copies
047   *    with or without payment, must accept this license for further using.
048   * <li> But the LPGL is not appropriate for a whole software product,
049   *    if this source is only a part of them. It means, the user
050   *    must publish this part of source,
051   *    but doesn't need to publish the whole source of the own product.
052   * <li> You can study and modify (improve) this source
053   *    for own using or for redistribution, but you have to license the
054   *    modified sources likewise under this LGPL Lesser General Public License.
055   *    You mustn't delete this Copyright/Copyleft inscription in this source file.
056   * </ol>
057   * If you intent to use this source without publishing its usage, you can get
058   * a second license subscribing a special contract with the author. 
059   * 
060   * @author Hartmut Schorrig = hartmut.schorrig@vishia.de
061   */
062  //@SuppressWarnings("hiding")
063  public static final int version = 20130524;
064
065  /**It contains the association to the swt widget (Control) and the {@link SwtMng}
066   * and implements some methods of {@link GralWidgImpl_ifc} which are delegate from this.
067   */
068  private final SwtWidgetHelper swtWidgHelper;
069  
070  Canvas widgetSwt;
071  
072  final Color black;
073  final Color white;
074  
075  final Font fontText;
076  
077  
078  final SwtGralMouseListener.MouseListenerGralAction mouseListener;
079  
080
081  
082  //public SwtButton(String sName, SwtMng mng, Composite parent, int styleSwt, char size)
083  SwtButton(GralButton widgg, SwtMng mng)
084  {
085    widgg.super(widgg, mng.mng);
086    widgg.setActionMouse(mouseWidgetAction, 0);
087    mouseListener = new SwtGralMouseListener.MouseListenerGralAction();
088    //Control xx = mng.pos.panel.panelComposite;
089    black = mng.propertiesGuiSwt.colorSwt(0x202020);
090    white = mng.propertiesGuiSwt.colorSwt(0xffffff);
091    Composite panelSwt = mng.getCurrentPanel();
092    int styleSwt = 0;
093    widgetSwt = new SwtButtonImpl(panelSwt, styleSwt);
094    widgetSwt.setData(this);
095    widgetSwt.setBackground(mng.propertiesGuiSwt.colorBackground);
096    widgetSwt.addMouseListener(mouseListener);
097    widgetSwt.addFocusListener(mng.focusListener);  //common focus listener 
098    widgetSwt.addKeyListener(new KeyListener(mng.mng._impl.gralKeyListener));
099    widgetSwt.addTraverseListener(SwtMng.swtTraverseListener);
100    setBoundsGraphic(widgg.pos(), mng);
101    float ySize = widgg.pos().height();
102    char size1 = ySize > 3? 'B' : 'A';
103    switch(size1){ 
104      case 'A': fontText = mng.propertiesGuiSwt.stdInputFont; break;
105      case 'B': fontText = mng.propertiesGuiSwt.stdButtonFont; break;
106      default: throw new IllegalArgumentException("param size must be A or B");
107    }
108    super.wdgimpl = swtWidgHelper = new SwtWidgetHelper(widgetSwt, mng);  
109  }
110
111
112  
113  @Override public GralRectangle getPixelPositionSize(){ return swtWidgHelper.getPixelPositionSize(); }
114
115  
116  void setBoundsGraphic(GralPos pos, SwtMng mng)
117  {
118    //widgetSwt.setSize(mng.propertiesGui.xPixelUnit() * xSize -2, mng.propertiesGui.yPixelUnit() * ySize -2);
119    mng.setBounds_(pos, widgetSwt);
120    
121  }
122  
123
124  
125  
126  @Override public void removeWidgetImplementation()
127  { swtWidgHelper.removeWidgetImplementation();
128    widgetSwt = null;
129  }
130
131  @Override
132  public Object getWidgetImplementation()
133  { return widgetSwt; }
134
135  @Override public void setBoundsPixel(int x, int y, int dx, int dy)
136  { widgetSwt.setBounds(x,y,dx,dy);
137  }
138  
139  @Override public boolean setFocusGThread()
140  { SwtWidgetHelper.setFocusOfTabSwt(widgetSwt);
141    widgetSwt.forceFocus();
142    return widgetSwt.setFocus();
143  }
144
145
146  /**Sets the implementation widget vible or not.
147   * @see org.vishia.gral.base.GralWidgImpl_ifc#setVisibleGThread(boolean)
148   */
149  @Override public void setVisibleGThread(boolean bVisible) { 
150    super.setVisibleState(bVisible); 
151    swtWidgHelper.setVisibleGThread(bVisible);
152  }
153  
154  @Override public void repaintGthread(){
155    super.prepareWidget();
156    GralWidget.DynamicData dyda = dyda();
157    int chg = dyda.getChanged();
158    if((chg & chgText) !=0 && dyda.displayedText !=null){ 
159      //textFieldSwt.setText(dyda.displayedText);
160    }
161    if((chg & chgColorText)!=0){
162      acknChanged(chgColorText);
163      SwtProperties props = swtWidgHelper.mng.propertiesGuiSwt;
164      if(dyda.textColor !=null){
165        widgetSwt.setForeground(props.colorSwt(dyda.textColor));
166      }
167      if(dyda.backColor !=null){
168        widgetSwt.setBackground(props.colorSwt(dyda.backColor));
169      }
170      if(dyda.textFont !=null){
171        widgetSwt.setFont(props.fontSwt(dyda.textFont));
172      }
173    }
174    if((chg & chgVisible) !=0) {
175      acknChanged(chgVisible);
176      widgetSwt.setVisible(true);
177      //widgetSwt.getShell().setVisible(true);
178    }
179    if((chg & chgInvisible) !=0) {
180      acknChanged(chgInvisible);
181      widgetSwt.setVisible(false);
182      //widgetSwt.getShell().setVisible(false);
183    }
184    if((chg & chgColorText) !=0){ acknChanged(chgColorText); widgetSwt.setForeground(swtWidgHelper.mng.getColorImpl(dyda().textColor)); }
185    if((chg & chgColorBack) !=0){ acknChanged(chgColorBack); widgetSwt.setBackground(swtWidgHelper.mng.getColorImpl(dyda().backColor)); }
186    widgetSwt.redraw();
187  }
188
189  
190  protected void paintRoutine(PaintEvent e, Canvas canvas){
191    GC gc = e.gc;
192    //gc.d
193    Rectangle dim = canvas.getBounds();
194    SwtButton.this.paint1();
195    boolean bFocus = canvas.isFocusControl();
196    Color colorBack = swtWidgHelper.mng.getColorImpl(colorgback);
197    Color colorLine = swtWidgHelper.mng.getColorImpl(colorgline);
198    if(bFocus) {
199      colorLine = swtWidgHelper.mng.getColorImpl(GralColor.getColor("rd"));
200    }
201    gc.setBackground(colorBack);
202    canvas.drawBackground(e.gc, dim.x+1, dim.y+1, dim.width-1, dim.height-1);
203    //Color color = canvas.getForeground(); //of the widget.
204    gc.setForeground(colorLine);  //black
205    gc.setFont(fontText);
206    //FontData fontData = mng.propertiesGui.stdButtonFont.getFontData();
207    //fontData.
208    gc.setForeground(colorBack);
209    gc.fillRectangle(1,1,dim.width-1, dim.height-1);
210    int ypText;
211    if(sButtonText !=null){
212      FontMetrics fontMetrics = gc.getFontMetrics();
213      int charWidth = fontMetrics.getAverageCharWidth();
214      int halfWidthButtonText = charWidth * sButtonText.length() /2;
215      int xText = dim.width / 2 - halfWidthButtonText;
216      if(xText < 2){ xText = 2; }
217      ypText = fontMetrics.getHeight();
218      int halfHeightButtonText = ypText /2;
219      int yText = dim.height / 2 - halfHeightButtonText;
220      gc.setForeground(colorLine);
221      gc.drawString(sButtonText, xText, yText);
222    } else {
223      ypText = 0;
224    }
225    if(isPressed()){
226      ((Canvas)e.widget).forceFocus();
227      /*
228      gc.setLineWidth(3);
229      gc.drawRectangle(1,1,dim.width-2, dim.height-2);
230      gc.setLineStyle(SWT.LINE_DOT);
231      gc.drawRectangle(3,3,dim.width-6, dim.height-6);
232      */
233      if(ypText < dim.height -4){
234        //normal button
235        gc.setForeground(black);
236        gc.setLineWidth(3);
237        gc.drawRectangle(0,0,dim.width-1, dim.height-1);
238        gc.setForeground(white); 
239        gc.setLineWidth(1);
240        gc.drawLine(2, dim.height-2,dim.width-1, dim.height-2);
241        gc.drawLine(1, dim.height-1,dim.width-1, dim.height-1);
242        gc.drawLine(0, dim.height-0,dim.width-1, dim.height-0);
243        gc.drawLine(dim.width-2, 0, dim.width-2, dim.height-1);
244        gc.drawLine(dim.width-1, 0, dim.width-1, dim.height-1);
245        gc.drawLine(dim.width-0, 0, dim.width-0, dim.height-1);
246      } else {
247        //small button
248        gc.setLineWidth(1);
249        gc.setForeground(black);
250        gc.setLineWidth(1);
251        gc.drawRectangle(0,0,dim.width-1, dim.height-1);
252        gc.setForeground(white); 
253        gc.setLineWidth(1);
254        gc.drawLine(0, dim.height-1,dim.width-1, dim.height-1);
255        gc.drawLine(dim.width-1, 0, dim.width-1, dim.height-1);
256      }
257    } else {
258      if(ypText < dim.height -4){
259        //normal button
260        gc.setForeground(white);
261        gc.setLineWidth(3);
262        gc.drawRectangle(0,0,dim.width-1, dim.height-1);
263        gc.setForeground(black); 
264        gc.setLineWidth(1);
265        gc.drawLine(2, dim.height-2,dim.width-1, dim.height-2);
266        gc.drawLine(1, dim.height-1,dim.width-1, dim.height-1);
267        gc.drawLine(0, dim.height-0,dim.width-1, dim.height-0);
268        gc.drawLine(dim.width-2, 0, dim.width-2, dim.height-1);
269        gc.drawLine(dim.width-1, 0, dim.width-1, dim.height-1);
270        gc.drawLine(dim.width-0, 0, dim.width-0, dim.height-1);
271      } else {
272        //small button
273        gc.setLineWidth(1);
274        gc.setForeground(white);
275        gc.setLineWidth(1);
276        gc.drawRectangle(0,0,dim.width-1, dim.height-1);
277        gc.setForeground(black); 
278        gc.setLineWidth(1);
279        gc.drawLine(0, dim.height-1,dim.width-1, dim.height-1);
280        gc.drawLine(dim.width-1, 0, dim.width-1, dim.height-1);
281      }
282    }
283    
284  }
285  
286  
287  
288  
289  private class SwtButtonImpl extends Canvas
290  {
291    
292    SwtButtonImpl(Composite parent, int style){
293      super(parent, style);
294      setForeground(black);
295      
296      addPaintListener(paintListener);  
297      
298    }
299    
300    PaintListener paintListener = new PaintListener(){
301      @Override public void paintControl(PaintEvent e) {
302        SwtButton.this.paintRoutine(e, SwtButtonImpl.this);
303      }
304    };
305    
306
307    
308  }
309  
310  
311  protected class KeyListener extends SwtKeyListener
312  {
313
314    public KeyListener(GralKeyListener keyAction)
315    { super(keyAction);
316    }
317
318    @SuppressWarnings("synthetic-access") 
319    @Override 
320    public final boolean specialKeysOfWidgetType(int key, GralWidget_ifc widggArg, Object widgImpl){ 
321      boolean bDone = true;
322      if(key == KeyCode.enter) {
323        widgg.activate();
324      }
325      return bDone; 
326    }
327  };
328
329  
330  
331  
332  
333}