Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 275117 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/swt/internal/widgets/linkkit/LinkLCA.java (-61 / +28 lines)
Lines 18-60 Link Here
18
import org.eclipse.rwt.internal.lifecycle.JSConst;
18
import org.eclipse.rwt.internal.lifecycle.JSConst;
19
import org.eclipse.rwt.internal.service.ContextProvider;
19
import org.eclipse.rwt.internal.service.ContextProvider;
20
import org.eclipse.rwt.lifecycle.*;
20
import org.eclipse.rwt.lifecycle.*;
21
import org.eclipse.swt.SWT;
21
import org.eclipse.swt.events.SelectionEvent;
22
import org.eclipse.swt.events.SelectionEvent;
22
import org.eclipse.swt.graphics.Point;
23
import org.eclipse.swt.graphics.Point;
23
import org.eclipse.swt.internal.widgets.ILinkAdapter;
24
import org.eclipse.swt.internal.widgets.ILinkAdapter;
25
import org.eclipse.swt.internal.widgets.Props;
24
import org.eclipse.swt.widgets.*;
26
import org.eclipse.swt.widgets.*;
25
27
26
/**
28
/**
27
 * Life-cycle adapter for the Link widget
29
 * Life-cycle adapter for the Link widget
28
 */
30
 */
29
public class LinkLCA extends AbstractWidgetLCA {
31
public class LinkLCA extends AbstractWidgetLCA {
32
  
33
  //Constants for JS functions names
34
  private static final String JS_FUNC_ADDTEXT = "addText";
35
  private static final String JS_FUNC_ADDLINK = "addLink";
36
  private static final String JS_FUNC_APPLYTEXT = "applyText";
37
  private static final String JS_FUNC_CLEAR = "clear";
30
38
31
  private static final String QX_TYPE = "qx.ui.layout.HorizontalBoxLayout";
39
  //Property names for preserveValues
32
33
//  private static final String TYPE_POOL_ID = LinkLCA.class.getName();
34
35
  private static final String JS_LINK_UTIL = "org.eclipse.swt.LinkUtil";
36
  private static final String JS_FUNC_INIT = JS_LINK_UTIL + ".init";
37
  private static final String JS_FUNC_ADD_LINK = JS_LINK_UTIL + ".addLink";
38
  private static final String JS_FUNC_ADD_TEXT = JS_LINK_UTIL + ".addText";
39
  private static final String JS_FUNC_ADD_STATE = JS_LINK_UTIL + ".addState";
40
  private static final String JS_FUNC_REMOVE_STATE
41
    = JS_LINK_UTIL + ".removeState";
42
  private static final String JS_FUNC_CLEAR = JS_LINK_UTIL + ".clear";
43
  private static final String JS_FUNC_DESTROY = JS_LINK_UTIL + ".destroy";
44
  private static final String JS_FUNC_SET_SELECTION_LISTENER
45
    = JS_LINK_UTIL + ".setSelectionListener";
46
47
  private static final String PROP_TEXT = "text";
40
  private static final String PROP_TEXT = "text";
48
  private static final String PROP_VARIANT = "variant";
49
  static final String PROP_SEL_LISTENER = "selectionListener";
50
41
51
  public void preserveValues( final Widget widget ) {
42
  public void preserveValues( final Widget widget ) {
52
    Link link = ( Link )widget;
43
    Link link = ( Link )widget;
53
    ControlLCAUtil.preserveValues( link );
44
    ControlLCAUtil.preserveValues( link );
54
    IWidgetAdapter adapter = WidgetUtil.getAdapter( widget );
45
    IWidgetAdapter adapter = WidgetUtil.getAdapter( widget );
55
    adapter.preserve( PROP_TEXT, link.getText() );
46
    adapter.preserve( PROP_TEXT, link.getText() );
56
    Boolean newValue = Boolean.valueOf( SelectionEvent.hasListener( link ) );
47
    boolean hasListeners = SelectionEvent.hasListener( link );
57
    adapter.preserve( PROP_SEL_LISTENER, newValue );
48
    adapter.preserve( Props.SELECTION_LISTENERS,
49
                      Boolean.valueOf( hasListeners ) );
58
    WidgetLCAUtil.preserveCustomVariant( link );
50
    WidgetLCAUtil.preserveCustomVariant( link );
59
  }
51
  }
60
52
Lines 68-77 Link Here
68
  public void renderInitialization( final Widget widget ) throws IOException {
60
  public void renderInitialization( final Widget widget ) throws IOException {
69
    Link link = ( Link )widget;
61
    Link link = ( Link )widget;
70
    JSWriter writer = JSWriter.getWriterFor( link );
62
    JSWriter writer = JSWriter.getWriterFor( link );
71
    writer.newWidget( QX_TYPE );
63
    writer.newWidget( "org.eclipse.swt.widgets.Link" );
72
    writer.set( JSConst.QX_FIELD_APPEARANCE, "link" );
73
    Object[] args = new Object[] { widget };
74
    writer.callStatic( JS_FUNC_INIT, args );
75
    ControlLCAUtil.writeStyleFlags( link );
64
    ControlLCAUtil.writeStyleFlags( link );
76
  }
65
  }
77
66
Lines 80-92 Link Here
80
    ControlLCAUtil.writeChanges( link );
69
    ControlLCAUtil.writeChanges( link );
81
    writeSelectionListener( link );
70
    writeSelectionListener( link );
82
    writeText( link );
71
    writeText( link );
83
    writeCustomVariant( link );
72
    WidgetLCAUtil.writeCustomVariant( link );
84
  }
73
  }
85
74
86
  public void renderDispose( final Widget widget ) throws IOException {
75
  public void renderDispose( final Widget widget ) throws IOException {
87
    JSWriter writer = JSWriter.getWriterFor( widget );
76
    JSWriter writer = JSWriter.getWriterFor( widget );
88
    Object[] args = new Object[]{ widget };
89
    writer.callStatic( JS_FUNC_DESTROY, args );
90
    writer.dispose();
77
    writer.dispose();
91
  }
78
  }
92
79
Lines 94-102 Link Here
94
    throws IOException
81
    throws IOException
95
  {
82
  {
96
    ControlLCAUtil.resetStyleFlags();
83
    ControlLCAUtil.resetStyleFlags();
97
    JSWriter writer = JSWriter.getWriterForResetHandler();
98
    Object[] args = new Object[]{ JSWriter.WIDGET_REF };
99
    writer.callStatic( JS_FUNC_CLEAR, args );
100
  }
84
  }
101
85
102
  public String getTypePoolId( final Widget widget ) {
86
  public String getTypePoolId( final Widget widget ) {
Lines 108-120 Link Here
108
  private static void writeSelectionListener( final Link link )
92
  private static void writeSelectionListener( final Link link )
109
    throws IOException
93
    throws IOException
110
  {
94
  {
111
    Boolean newValue = Boolean.valueOf( SelectionEvent.hasListener( link ) );
95
    boolean hasListener = SelectionEvent.hasListener( link );
112
    Boolean defValue = Boolean.FALSE;
96
    Boolean newValue = Boolean.valueOf( hasListener );
113
    String prop = PROP_SEL_LISTENER;
97
    String prop = Props.SELECTION_LISTENERS;
114
    if( WidgetLCAUtil.hasChanged( link, prop, newValue, defValue ) ) {
98
    if( WidgetLCAUtil.hasChanged( link, prop, newValue, Boolean.FALSE ) ) {
115
      JSWriter writer = JSWriter.getWriterFor( link );
99
      JSWriter writer = JSWriter.getWriterFor( link );
116
      Object[] args = new Object[]{ link, newValue };
100
      writer.set( "hasSelectionListener", newValue );
117
      writer.callStatic( JS_FUNC_SET_SELECTION_LISTENER, args );
118
    }
101
    }
119
  }
102
  }
120
103
Lines 122-129 Link Here
122
    String newValue = link.getText();
105
    String newValue = link.getText();
123
    if( WidgetLCAUtil.hasChanged( link, PROP_TEXT, newValue, "" ) ) {
106
    if( WidgetLCAUtil.hasChanged( link, PROP_TEXT, newValue, "" ) ) {
124
      JSWriter writer = JSWriter.getWriterFor( link );
107
      JSWriter writer = JSWriter.getWriterFor( link );
125
      Object[] args = new Object[]{ link };
108
      writer.call( JS_FUNC_CLEAR, null );
126
      writer.callStatic( JS_FUNC_CLEAR, args );
127
      ILinkAdapter adapter
109
      ILinkAdapter adapter
128
        = ( ILinkAdapter )link.getAdapter( ILinkAdapter.class );
110
        = ( ILinkAdapter )link.getAdapter( ILinkAdapter.class );
129
      String displayText = adapter.getDisplayText();
111
      String displayText = adapter.getDisplayText();
Lines 147-152 Link Here
147
      if( pos < length ) {
129
      if( pos < length ) {
148
        writeNormalText( link, displayText.substring( pos, length ) );
130
        writeNormalText( link, displayText.substring( pos, length ) );
149
      }
131
      }
132
      writeApplyText( link );
150
    }
133
    }
151
  }
134
  }
152
135
Lines 155-166 Link Here
155
  {
138
  {
156
    JSWriter writer = JSWriter.getWriterFor( link );
139
    JSWriter writer = JSWriter.getWriterFor( link );
157
    Object[] args = new Object[] {
140
    Object[] args = new Object[] {
158
      link,
159
      // TODO [rst] mnemonics are already parsed by Link#parse()
141
      // TODO [rst] mnemonics are already parsed by Link#parse()
160
      //            Revise when we're going to support underline once
142
      //            Revise when we're going to support underline once
161
      WidgetLCAUtil.escapeText( text, false )
143
      WidgetLCAUtil.escapeText( text, false )
162
    };
144
    };
163
    writer.callStatic( JS_FUNC_ADD_TEXT, args );
145
    writer.call( JS_FUNC_ADDTEXT, args );
164
  }
146
  }
165
147
166
  private static void writeLinkText( final Link link,
148
  private static void writeLinkText( final Link link,
Lines 170-182 Link Here
170
  {
152
  {
171
    JSWriter writer = JSWriter.getWriterFor( link );
153
    JSWriter writer = JSWriter.getWriterFor( link );
172
    Object[] args = new Object[] {
154
    Object[] args = new Object[] {
173
      link,
174
      // TODO [rst] mnemonics are already parsed by Link#parse()
155
      // TODO [rst] mnemonics are already parsed by Link#parse()
175
      //            Revise when we're going to support underline once
156
      //            Revise when we're going to support underline once
176
      WidgetLCAUtil.escapeText( text, false ),
157
      WidgetLCAUtil.escapeText( text, false ),
177
      new Integer( index )
158
      new Integer( index )
178
    };
159
    };
179
    writer.callStatic( JS_FUNC_ADD_LINK, args );
160
    writer.call( JS_FUNC_ADDLINK, args );
161
  }
162
  
163
  private static void writeApplyText( final Link link ) throws IOException {
164
    JSWriter writer = JSWriter.getWriterFor( link );
165
    writer.call( JS_FUNC_APPLYTEXT, null );
180
  }
166
  }
181
167
182
  private static void processSelectionEvent( final Link link ) {
168
  private static void processSelectionEvent( final Link link ) {
Lines 197-219 Link Here
197
      }
183
      }
198
    }
184
    }
199
  }
185
  }
200
201
  private static void writeCustomVariant( final Link link )
202
    throws IOException
203
  {
204
    IWidgetAdapter adapter = WidgetUtil.getAdapter( link );
205
    String oldValue = ( String )adapter.getPreserved( PROP_VARIANT );
206
    String newValue = WidgetUtil.getVariant( link );
207
    if( WidgetLCAUtil.hasChanged( link, PROP_VARIANT, newValue, null ) ) {
208
      JSWriter writer = JSWriter.getWriterFor( link );
209
      Object[] args = new Object[] { link, "variant_" + oldValue };
210
      if( oldValue != null ) {
211
        writer.callStatic( JS_FUNC_REMOVE_STATE, args );
212
      }
213
      if( newValue != null ) {
214
        args = new Object[] { link, "variant_" + newValue };
215
        writer.callStatic( JS_FUNC_ADD_STATE, args );
216
      }
217
    }
218
  }
219
}
186
}
(-)src/org/eclipse/swt/internal/widgets/displaykit/QooxdooResourcesUtil.java (-3 / +3 lines)
Lines 58-65 Link Here
58
    = "org/eclipse/swt/ToolItemUtil.js";
58
    = "org/eclipse/swt/ToolItemUtil.js";
59
  private static final String MENU_UTIL_JS
59
  private static final String MENU_UTIL_JS
60
    = "org/eclipse/swt/MenuUtil.js";
60
    = "org/eclipse/swt/MenuUtil.js";
61
  private static final String LINK_UTIL_JS
62
    = "org/eclipse/swt/LinkUtil.js";
63
  private static final String WIDGET_UTIL_JS
61
  private static final String WIDGET_UTIL_JS
64
    = "org/eclipse/swt/WidgetUtil.js";
62
    = "org/eclipse/swt/WidgetUtil.js";
65
  private static final String CTAB_FOLDER_JS
63
  private static final String CTAB_FOLDER_JS
Lines 140-145 Link Here
140
    = "org/eclipse/swt/widgets/CheckBox.js";
138
    = "org/eclipse/swt/widgets/CheckBox.js";
141
  private static final String RADIOBUTTON_JS
139
  private static final String RADIOBUTTON_JS
142
    = "org/eclipse/swt/widgets/RadioButton.js";
140
    = "org/eclipse/swt/widgets/RadioButton.js";
141
  private static final String LINK_JS
142
    = "org/eclipse/swt/widgets/Link.js";
143
143
144
  private QooxdooResourcesUtil() {
144
  private QooxdooResourcesUtil() {
145
    // prevent intance creation
145
    // prevent intance creation
Lines 205-211 Link Here
205
      register( TABLE_COLUMN_JS, compress );
205
      register( TABLE_COLUMN_JS, compress );
206
      register( TABLE_ITEM_JS, compress );
206
      register( TABLE_ITEM_JS, compress );
207
      register( TABLE_ROW_JS, compress );
207
      register( TABLE_ROW_JS, compress );
208
      register( LINK_UTIL_JS, compress );
209
      register( EXTERNALBROWSER_JS, compress );
208
      register( EXTERNALBROWSER_JS, compress );
210
      register( BROWSER_JS, compress );
209
      register( BROWSER_JS, compress );
211
      register( PROGRESS_BAR_JS, compress );
210
      register( PROGRESS_BAR_JS, compress );
Lines 221-226 Link Here
221
      register( SLIDER_JS, compress );
220
      register( SLIDER_JS, compress );
222
      register( CHECKBOX_JS, compress );
221
      register( CHECKBOX_JS, compress );
223
      register( RADIOBUTTON_JS, compress );
222
      register( RADIOBUTTON_JS, compress );
223
      register( LINK_JS, compress );
224
224
225
      // register contributions
225
      // register contributions
226
      registerContributions();
226
      registerContributions();
(-)js/org/eclipse/swt/LinkUtil.js (-160 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2002, 2009 Innoopract Informationssysteme GmbH.
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
 *     Innoopract Informationssysteme GmbH - initial API and implementation
10
 ******************************************************************************/
11
12
/**
13
 * This class contains static functions needed for the SWT Link widget.
14
 */
15
qx.Class.define( "org.eclipse.swt.LinkUtil", {
16
17
  statics : {
18
    init : function( widget ) {
19
      widget.setTabIndex( -1 );
20
      widget.setUserData( "nextTabIndex", 0 );
21
      widget.addEventListener( "changeTabIndex",
22
                               org.eclipse.swt.LinkUtil._onTabIndexChange );
23
    },
24
25
    destroy : function( widget ) {
26
      org.eclipse.swt.LinkUtil.clear( widget );
27
      if( widget.hasEventListeners( "changeTabIndex" ) ) {
28
        widget.removeEventListener( "changeTabIndex",
29
                                    org.eclipse.swt.LinkUtil._onTabIndexChange );
30
      }
31
    },
32
33
    clear : function( widget ) {
34
      if( widget && !widget.getDisposed() ) {
35
        var children = widget.getChildren();
36
        var child = children[ 0 ];
37
        while( child ) {
38
          widget.remove( child );
39
          if( child.hasEventListeners( "mousedown" ) ) {
40
            child.removeEventListener( "mousedown",
41
                                       org.eclipse.swt.LinkUtil._onMouseDown );
42
          }
43
          if( child.hasEventListeners( "keydown" ) ) {
44
            child.removeEventListener( "keydown",
45
                                       org.eclipse.swt.LinkUtil._onKeyDown );
46
          }          
47
          child.dispose();
48
          child = children[ 0 ];
49
        }
50
      }
51
    },
52
    
53
    addState : function( widget, state ) {
54
      if( widget ) {
55
        if( state.substr( 0, 8 ) == "variant_" ) {
56
          widget.addState( state );
57
          var children = widget.getChildren();
58
          for( var i = 0; i < children.length; i++ ) {
59
            children[ i ].addState( state );
60
          }
61
        }
62
      }
63
    },
64
65
    removeState : function( widget, state ) {
66
      if( widget ) {
67
        if( state.substr( 0, 8 ) == "variant_" ) {
68
          widget.removeState( state );
69
          var children = widget.getChildren();
70
          for( var i = 0; i < children.length; i++ ) {
71
            children[ i ].removeState( state );
72
          }
73
        }
74
      }
75
    },
76
77
    setSelectionListener : function( widget, value ) {
78
      widget.setUserData( "widgetSelectedListener", value );
79
    },
80
81
    addText : function( widget, text ) {
82
      if( widget ) {
83
        var newChild = org.eclipse.swt.LinkUtil._createLabel( widget, text );
84
        newChild.setAppearance( "link-text" );
85
        newChild.setWrap( false );
86
        widget.add( newChild );
87
      }
88
    },
89
90
    addLink : function( widget, text, index ) {
91
      if( widget ) {
92
        uText = "<u>" + text + "</u>";
93
        var newChild = org.eclipse.swt.LinkUtil._createLabel( widget, uText );
94
        newChild.setUserData( "index", index );
95
        newChild.setAppearance( "link-href" );
96
        newChild.setWrap( false );
97
        widget.add( newChild );
98
        var tabIndex = widget.getUserData( "nextTabIndex" );
99
        newChild.setTabIndex( tabIndex++ );
100
        widget.setUserData( "nextTabIndex", tabIndex );
101
        newChild.addEventListener( "mousedown",
102
                                   org.eclipse.swt.LinkUtil._onMouseDown,
103
                                   newChild );
104
        newChild.addEventListener( "keydown",
105
                                   org.eclipse.swt.LinkUtil._onKeyDown,
106
                                   newChild );
107
      }
108
    },
109
110
    _createLabel : function( parent, text ) {
111
      // replace spaces with nbsp
112
      var replaced = text.replace( /\s/g, "&nbsp;" );
113
      var label = new qx.ui.basic.Label( replaced, null, "html" );
114
      return label;
115
    },
116
117
    _onMouseDown : function( evt ) {
118
      var parent = this.getParent();
119
      if( parent.getUserData( "widgetSelectedListener" ) ) {
120
        var req = org.eclipse.swt.Request.getInstance();
121
        var wm = org.eclipse.swt.WidgetManager.getInstance();
122
        var id = wm.findIdByWidget( parent );
123
        var index = this.getUserData( "index" );
124
        req.addEvent( "org.eclipse.swt.events.widgetSelected", id );
125
        req.addEvent( "org.eclipse.swt.events.widgetSelected.index", index );
126
        req.send();
127
      }
128
    },
129
130
    _onKeyDown : function( evt ) {
131
      var keyId = evt.getKeyIdentifier();
132
      if ( keyId == "Enter" ) {
133
        var parent = this.getParent();
134
        if( parent.getUserData( "widgetSelectedListener" ) ) {
135
          var req = org.eclipse.swt.Request.getInstance();
136
          var wm = org.eclipse.swt.WidgetManager.getInstance();
137
          var id = wm.findIdByWidget( parent );
138
          var index = this.getUserData( "index" );
139
          req.addEvent( "org.eclipse.swt.events.widgetSelected", id );
140
          req.addEvent( "org.eclipse.swt.events.widgetSelected.index", index );
141
          req.send();
142
        }
143
      }
144
    },
145
146
    _onTabIndexChange : function( evt ) {
147
      var tabIndex = evt.getValue();
148
      if( tabIndex >= 0 ) {
149
        var target = evt.getCurrentTarget();
150
        var children = target.getChildren();
151
        for( var i = 0; i < children.length; i++ ) {
152
          child = children[ i ];
153
          child.setTabIndex( tabIndex++ );
154
        }
155
        target.setUserData( "nextTabIndex", tabIndex );
156
        target.setTabIndex( -1 );
157
      }
158
    }
159
  }
160
});
(-)js/org/eclipse/swt/theme/AppearancesBase.js (-11 / +2 lines)
Lines 1590-1595 Link Here
1590
      var tv = new org.eclipse.swt.theme.ThemeValues( states );
1590
      var tv = new org.eclipse.swt.theme.ThemeValues( states );
1591
      return {
1591
      return {
1592
        cursor: "default",
1592
        cursor: "default",
1593
        padding : 2,
1593
        font : tv.getCssFont( "Link", "font" ),
1594
        font : tv.getCssFont( "Link", "font" ),
1594
        border : tv.getCssBorder( "Link", "border" ),
1595
        border : tv.getCssBorder( "Link", "border" ),
1595
        textColor : tv.getCssColor( "*", "color" )
1596
        textColor : tv.getCssColor( "*", "color" )
Lines 1601-1619 Link Here
1601
    style : function( states ) {
1602
    style : function( states ) {
1602
      var tv = new org.eclipse.swt.theme.ThemeValues( states );
1603
      var tv = new org.eclipse.swt.theme.ThemeValues( states );
1603
      return {
1604
      return {
1604
        textColor : states.disabled ? "widget.graytext" : "undefined"
1605
      }
1606
    }
1607
  },
1608
1609
  "link-href" : {
1610
    style : function( states ) {
1611
      var tv = new org.eclipse.swt.theme.ThemeValues( states );
1612
      return {
1613
        cursor : states.disabled ? "default" : "pointer",
1614
        textColor: states.disabled
1605
        textColor: states.disabled
1615
                   ? "widget.graytext"
1606
                   ? "widget.graytext"
1616
                   : tv.getCssColor( "Link-Hyperlink", "color" )
1607
                   : "inherit"
1617
      }
1608
      }
1618
    }
1609
    }
1619
  },
1610
  },
(-)js/org/eclipse/swt/widgets/Link.js (+342 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Innoopract Informationssysteme GmbH. All rights reserved.
3
 * This program and the accompanying materials are made available under the
4
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
5
 * and is available at http://www.eclipse.org/legal/epl-v10.html
6
 *
7
 * Contributors: Innoopract Informationssysteme GmbH - initial API and
8
 * implementation
9
 ******************************************************************************/
10
11
/**
12
 * This class provides the client-side implementation for
13
 * org.eclipse.swt.widgets.Link
14
 */
15
qx.Class.define( "org.eclipse.swt.widgets.Link", {
16
  extend : qx.ui.layout.CanvasLayout,
17
18
  construct : function() {
19
    this.base( arguments );
20
    this.setAppearance( "link" );
21
    // Default values
22
    this._text = "";
23
    this._hasSelectionListener = false;
24
    this._hyperlinksHaveListeners = false;
25
    this._linkColor;
26
    // innerTab handling
27
    this._currentLinkFocused = -1;
28
    this._linksCount = 0;        
29
    //
30
    this._link = new qx.ui.embed.HtmlEmbed();
31
    this._link.setAppearance( "link-text" );
32
    this.add( this._link );
33
    //
34
    this.setSelectable( false );
35
    this.setHideFocus( true );
36
    //
37
    this.__onMouseDown = qx.lang.Function.bindEvent( this._onMouseDown, this );
38
    this.__onKeyDown = qx.lang.Function.bindEvent( this._onKeyDown, this );
39
    //
40
    this.addEventListener( "appear", this._onAppear, this );
41
    this.addEventListener( "changeEnabled", this._onChangeEnabled, this );
42
    this.addEventListener( "contextmenu", this._onContextMenu, this );
43
    // Event listener used for inner TabIndex change
44
    this.addEventListener( "keypress", this._onKeyPress );
45
    this.addEventListener( "focusout", this._onFocusOut );
46
    //
47
    this._link.addEventListener( "changeHtml", this._onChangeHtml, this );
48
  },
49
50
  destruct : function() {
51
    this._removeEventListeners();
52
    delete this.__onMouseDown;
53
    delete this.__onKeyDown;
54
    this.removeEventListener( "appear", this._onAppear, this );
55
    this.removeEventListener( "contextmenu", this._onContextMenu, this );
56
    this.removeEventListener( "changeEnabled", this._onChangeEnabled, this );
57
    this.removeEventListener( "keypress", this._onKeyPress );
58
    this.removeEventListener( "focusout", this._onFocusOut );
59
    this._link.removeEventListener( "changeHtml", this._onChangeHtml, this );
60
    this._link.dispose();
61
  },
62
63
  members : {
64
    _onContextMenu : function( evt ) {
65
      var menu = this.getContextMenu();
66
      if( menu != null ) {
67
        menu.setLocation( evt.getPageX(), evt.getPageY() );
68
        menu.setOpener( this );
69
        menu.show();
70
        evt.stopPropagation();
71
      }
72
    },
73
    
74
  	_onAppear : function( evt ) {
75
      this._link.setTabIndex( -1 );
76
      this._link.setHideFocus( true );
77
      this._applyHyperlinksStyleProperties();
78
      this._addEventListeners();
79
  	},
80
  	
81
  	_onChangeHtml : function( evt ) {
82
      this._applyHyperlinksStyleProperties();
83
      this._addEventListeners();
84
  	},
85
  	
86
  	_applyTextColor : function( value, old ) {
87
      this.base( arguments, value, old );
88
      var themeValues 
89
        = new org.eclipse.swt.theme.ThemeValues( this._getStates() );
90
      this._linkColor = themeValues.getCssColor( "Link-Hyperlink", "color" );
91
      themeValues.dispose();
92
      this._applyHyperlinksStyleProperties();
93
  	},
94
  	
95
  	_onChangeEnabled : function( evt ) {      
96
      this._applyHyperlinksStyleProperties();
97
      this._changeHyperlinksTabIndexProperty();
98
  	},
99
  	
100
  	_getStates : function() {
101
      if( !this.__states ) {
102
        this.__states = {};
103
      }
104
      return this.__states;
105
  	},
106
    
107
    addState : function( state ) {
108
      this.base( arguments, state );
109
      this._link.addState( state );
110
    },
111
    
112
    removeState : function( state ) {
113
      this.base( arguments, state );
114
      this._link.removeState( state );
115
    },
116
117
    setHasSelectionListener : function( value ) {
118
      this._hasSelectionListener = value;
119
    },
120
       
121
    addText : function( text ) {
122
      this._text += text;
123
    },
124
125
    addLink : function( text, index ) {
126
      this._text += "<span tabIndex=\"1\" ";
127
      this._text += "style=\"";
128
      this._text += "text-decoration:underline; ";
129
      this._text += "\" ";
130
      this._text += "id=\"" + index + "\"";
131
      this._text += ">";
132
      this._text += text;
133
      this._text += "</span>";
134
      this._linksCount++;
135
    },
136
    
137
    applyText : function() {
138
      this._link.setHtml( this._text );
139
      if ( this._linksCount == 0 ) {
140
        this.setTabIndex( -1 );
141
      } else {
142
        this.setTabIndex( 1 );
143
      }
144
    },
145
    
146
    clear : function() {
147
      this._removeEventListeners();
148
      this._text = "";
149
      this._linksCount = 0;
150
    },
151
    
152
    _applyHyperlinksStyleProperties : function() {
153
      var linkElement = this.getElement();
154
      if( linkElement ) {
155
        var hyperlinks = linkElement.getElementsByTagName( "span" );
156
        for( i = 0; i < hyperlinks.length; i++ ) {
157
          if( this._linkColor ) {
158
            if( this.isEnabled() ) {
159
      	      hyperlinks[ i ].style.color = this._linkColor;
160
            } else {
161
              hyperlinks[ i ].style.color = "";
162
            }  
163
      	  }
164
      	  if( this.isEnabled() ) {
165
      	  	hyperlinks[ i ].style.cursor = "pointer";
166
      	  } else {
167
      	  	hyperlinks[ i ].style.cursor = "default";
168
      	  }
169
        }
170
      }
171
    },
172
    
173
    _changeHyperlinksTabIndexProperty : function() {
174
      var linkElement = this.getElement();
175
      if( linkElement ) {
176
        var hyperlinks = linkElement.getElementsByTagName( "span" );
177
        for( i = 0; i < hyperlinks.length; i++ ) {
178
          if( this.isEnabled() ) {
179
            hyperlinks[ i ].tabIndex = "1";
180
          } else {
181
            hyperlinks[ i ].tabIndex = "-1";
182
          }
183
        }
184
      }
185
    },
186
    
187
    _addEventListeners : function() {
188
      var linkElement = this.getElement();
189
      if( linkElement && !this._hyperlinksHaveListeners ) {
190
        var hyperlinks = linkElement.getElementsByTagName( "span" );
191
        for( i = 0; i < hyperlinks.length; i++ ) {
192
          qx.html.EventRegistration.addEventListener( hyperlinks[ i ], 
193
                                                      "mousedown", 
194
                                                      this.__onMouseDown );
195
          qx.html.EventRegistration.addEventListener( hyperlinks[ i ], 
196
                                                      "keydown", 
197
                                                      this.__onKeyDown );
198
        }
199
        this._hyperlinksHaveListeners = true;
200
      }
201
    },
202
    
203
    _removeEventListeners : function() {
204
      var linkElement = this.getElement();
205
      if( linkElement && this._hyperlinksHaveListeners ) {
206
        var hyperlinks = linkElement.getElementsByTagName( "span" );
207
        for( i = 0; i < hyperlinks.length; i++ ) {
208
          qx.html.EventRegistration.removeEventListener( hyperlinks[ i ], 
209
                                                         "mousedown", 
210
                                                         this.__onMouseDown );
211
          qx.html.EventRegistration.removeEventListener( hyperlinks[ i ], 
212
                                                         "keydown", 
213
                                                         this.__onKeyDown );
214
        }
215
        this._hyperlinksHaveListeners = false;
216
      }
217
    },
218
    
219
    _onMouseDown : function( e ) {
220
      var target = this._getEventTarget( e );
221
      var index = target.id;
222
      this._currentLinkFocused = index;
223
      target.focus();
224
      var leftBtnPressed = this._isLeftMouseButtonPressed( e );
225
      if( this.isEnabled() && leftBtnPressed ) {
226
        this._sendChanges( index );
227
      }
228
    },
229
    
230
    _isLeftMouseButtonPressed : function( e ) {
231
      var leftBtnPressed;
232
      if( e.which ) {
233
        leftBtnPressed = ( e.which == 1 );
234
      } else if ( e.button ) {
235
        if( qx.core.Variant.isSet( "qx.client", "mshtml" ) ) {
236
          leftBtnPressed = ( e.button == 1 );
237
        } else {
238
          leftBtnPressed = ( e.button == 0 );
239
        }
240
      }
241
      return leftBtnPressed;
242
    },
243
    
244
    _onKeyDown : function( e ) {
245
      if( this.isEnabled() && e.keyCode == 13 ) {
246
        var target = this._getEventTarget( e );
247
        var index = target.id;
248
        this._sendChanges( index );
249
      }
250
    },
251
    
252
    _getEventTarget : function( e ) {
253
      var target;
254
      if( qx.core.Variant.isSet( "qx.client", "mshtml" ) ) {
255
        target = window.event.srcElement;
256
      } else {
257
        target = e.target;
258
      }
259
      return target;
260
    },
261
    
262
    // Override of the _ontabfocus method from qx.ui.core.Widget 
263
    _ontabfocus : function() {
264
      if( this._currentLinkFocused == -1 && this._linksCount > 0 ) {
265
        var linkElement = this.getElement();
266
        if( linkElement ) {
267
          var hyperlinks = linkElement.getElementsByTagName( "span" );
268
          hyperlinks[ 0 ].focus();
269
          this._currentLinkFocused = 0;
270
        }
271
      }
272
    },
273
    
274
    _onKeyPress : function( evt ) {
275
      if(    this.isFocused() 
276
          && evt.getKeyIdentifier() == "Tab" 
277
          && this._linksCount > 0 )
278
      {
279
        if(    !evt.isShiftPressed()
280
            && this._currentLinkFocused >= 0
281
            && this._currentLinkFocused < ( this._linksCount - 1 ) )
282
        {
283
          evt.stopPropagation();
284
          evt.preventDefault();
285
          this._currentLinkFocused++;
286
          this._focusLinkByID( this._currentLinkFocused );
287
        } else if(    !evt.isShiftPressed()
288
                   && this._currentLinkFocused == -1 )
289
        {
290
          evt.stopPropagation();
291
          evt.preventDefault();
292
          var linkElement = this.getElement();
293
          if( linkElement ) {
294
            var hyperlinks = linkElement.getElementsByTagName( "span" );
295
            hyperlinks[ 0 ].focus();
296
            this._currentLinkFocused = 0;
297
          }
298
        } else if(    evt.isShiftPressed()
299
                   && this._currentLinkFocused > 0
300
                   && this._currentLinkFocused <= ( this._linksCount - 1 ) )
301
        {
302
          evt.stopPropagation();
303
          evt.preventDefault();
304
          this._currentLinkFocused--;
305
          this._focusLinkByID( this._currentLinkFocused );
306
        }    
307
      }
308
    },
309
    
310
    _focusLinkByID : function( id ) {
311
      var linkElement = this.getElement();
312
      if( linkElement ) {
313
        var hyperlinks = linkElement.getElementsByTagName( "span" );
314
        hyperlinks[ id ].focus();
315
      }
316
    },
317
    
318
    _onFocusOut : function( evt ) {
319
      var linkElement = this.getElement();
320
      if( linkElement ) {
321
        var hyperlinks = linkElement.getElementsByTagName( "span" );
322
        if( this._currentLinkFocused >= 0 ) {
323
          hyperlinks[ this._currentLinkFocused ].blur();
324
        }
325
      }
326
      this._currentLinkFocused = -1;
327
    },
328
    
329
    _sendChanges : function( index ) {
330
      if( !org_eclipse_rap_rwt_EventUtil_suspend ) {
331
        var widgetManager = org.eclipse.swt.WidgetManager.getInstance();
332
        var id = widgetManager.findIdByWidget( this );
333
        var req = org.eclipse.swt.Request.getInstance();
334
        if( this._hasSelectionListener ) {
335
          req.addEvent( "org.eclipse.swt.events.widgetSelected", id );
336
          req.addEvent( "org.eclipse.swt.events.widgetSelected.index", index );
337
          req.send();
338
        }
339
      }
340
    }
341
  }
342
} );
(-)src/org/eclipse/swt/widgets/Link_Test.java (-6 / +18 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2002, 2007 Innoopract Informationssysteme GmbH.
2
 * Copyright (c) 2002, 2009 Innoopract Informationssysteme GmbH.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 62-89 Link Here
62
    assertEquals( "www.eclipse.org", ids[ 0 ] );
62
    assertEquals( "www.eclipse.org", ids[ 0 ] );
63
    assertEquals( "SWT", ids[ 1 ] );
63
    assertEquals( "SWT", ids[ 1 ] );
64
  }
64
  }
65
65
  
66
  public void testComputeSize() throws Exception {
66
  public void testComputeSize() throws Exception {
67
    RWTFixture.fakePhase( PhaseId.PROCESS_ACTION );
67
    RWTFixture.fakePhase( PhaseId.PROCESS_ACTION );
68
    Display display = new Display();
68
    Display display = new Display();
69
    Shell shell = new Shell( display , SWT.NONE );
69
    Shell shell = new Shell( display , SWT.NONE );
70
    Link link = new Link( shell, SWT.NONE );
70
    Link link = new Link( shell, SWT.NONE );
71
    Point expected = new Point( 0, 0 );
71
    Point expected = new Point( 4, 4 );
72
    assertEquals( expected, link.computeSize( SWT.DEFAULT, SWT.DEFAULT ) );
72
    assertEquals( expected, link.computeSize( SWT.DEFAULT, SWT.DEFAULT ) );
73
73
74
    String text
74
    String text
75
      = "Visit the <A HREF=\"www.eclipse.org\">Eclipse.org</A> project and "
75
      = "Visit the <A HREF=\"www.eclipse.org\">Eclipse.org</A> project and "
76
      + "the <a>SWT</a> homepage.";
76
      + "the <a>SWT</a> homepage.";
77
    link.setText( text );
77
    link.setText( text );
78
    expected = new Point( 269, 15 );
78
    expected = new Point( 273, 18 );
79
    assertEquals( expected, link.computeSize( SWT.DEFAULT, SWT.DEFAULT ) );
79
    assertEquals( expected, link.computeSize( SWT.DEFAULT, SWT.DEFAULT ) );
80
80
81
    link = new Link( shell, SWT.BORDER );
81
    link = new Link( shell, SWT.BORDER );
82
    expected = new Point( 2, 2 );
82
    expected = new Point( 8, 8 );
83
    assertEquals( expected, link.computeSize( SWT.DEFAULT, SWT.DEFAULT ) );
83
    assertEquals( expected, link.computeSize( SWT.DEFAULT, SWT.DEFAULT ) );
84
84
85
    expected = new Point( 102, 102 );
85
    expected = new Point( 108, 108 );
86
    assertEquals( expected, link.computeSize( 100, 100 ) );
86
    assertEquals( expected, link.computeSize( 100, 100 ) );
87
    
88
    text = "<a>test & test2</a>";
89
    link = new Link( shell, SWT.NONE );
90
    link.setText( text );
91
    expected = new Point( 62, 18 );
92
    assertEquals( expected, link.computeSize( SWT.DEFAULT, SWT.DEFAULT ) );
93
    
94
    text = "<a>test && test2</a>";
95
    link = new Link( shell, SWT.NONE );
96
    link.setText( text );
97
    expected = new Point( 73, 18 );
98
    assertEquals( expected, link.computeSize( SWT.DEFAULT, SWT.DEFAULT ) );
87
  }
99
  }
88
100
89
  protected void setUp() throws Exception {
101
  protected void setUp() throws Exception {
(-)js/org/eclipse/swt/LinkUtil.js (-138 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2002, 2008 Innoopract Informationssysteme GmbH.
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
 *     Innoopract Informationssysteme GmbH - initial API and implementation
10
 ******************************************************************************/
11
12
/**
13
 * This class contains static functions needed for the SWT Link widget.
14
 */
15
qx.Class.define( "org.eclipse.swt.LinkUtil", {
16
17
  statics : {
18
    init : function( widget ) {
19
      widget.setTabIndex( -1 );
20
      widget.setUserData( "nextTabIndex", 0 );
21
      widget.addEventListener( "changeTabIndex",
22
                               org.eclipse.swt.LinkUtil._onTabIndexChange );
23
    },
24
25
    destroy : function( widget ) {
26
      org.eclipse.swt.LinkUtil.clear( widget );
27
      if( widget.hasEventListeners( "changeTabIndex" ) ) {
28
        widget.removeEventListener( "changeTabIndex",
29
                                    org.eclipse.swt.LinkUtil._onTabIndexChange );
30
      }
31
    },
32
33
    clear : function( widget ) {
34
      if( widget && !widget.getDisposed() ) {
35
        var children = widget.getChildren();
36
        var child = children[ 0 ];
37
        while( child ) {
38
          widget.remove( child );
39
          if( child.hasEventListeners( "mousedown" ) ) {
40
            child.removeEventListener( "mousedown",
41
                                       org.eclipse.swt.LinkUtil._onMouseDown );
42
          }
43
          if( child.hasEventListeners( "keydown" ) ) {
44
            child.removeEventListener( "keydown",
45
                                       org.eclipse.swt.LinkUtil._onKeyDown );
46
          }          
47
          // TODO [if] Replace child.dispose() with child.destroy()
48
          // when qx 0.7.4 is in place
49
          child.dispose();
50
          child = children[ 0 ];
51
        }
52
      }
53
    },
54
55
    setSelectionListener : function( widget, value ) {
56
      widget.setUserData( "widgetSelectedListener", value );
57
    },
58
59
    addText : function( widget, text ) {
60
      if( widget ) {
61
        var newChild = org.eclipse.swt.LinkUtil._createLabel( widget, text );
62
        newChild.setAppearance( "link-text" );
63
        newChild.setWrap( false );
64
        widget.add( newChild );
65
      }
66
    },
67
68
    addLink : function( widget, text, index ) {
69
      if( widget ) {
70
        uText = "<u>" + text + "</u>";
71
        var newChild = org.eclipse.swt.LinkUtil._createLabel( widget, uText );
72
        newChild.setUserData( "index", index );
73
        newChild.setAppearance( "link-href" );
74
        newChild.setWrap( false );
75
        widget.add( newChild );
76
        var tabIndex = widget.getUserData( "nextTabIndex" );
77
        newChild.setTabIndex( tabIndex++ );
78
        widget.setUserData( "nextTabIndex", tabIndex );
79
        newChild.addEventListener( "mousedown",
80
                                   org.eclipse.swt.LinkUtil._onMouseDown,
81
                                   newChild );
82
        newChild.addEventListener( "keydown",
83
                                   org.eclipse.swt.LinkUtil._onKeyDown,
84
                                   newChild );
85
      }
86
    },
87
88
    _createLabel : function( parent, text ) {
89
      // replace spaces with nbsp
90
      var replaced = text.replace( /\s/g, "&nbsp;" );
91
      var label = new qx.ui.basic.Label( replaced, null, "html" );
92
      return label;
93
    },
94
95
    _onMouseDown : function( evt ) {
96
      var parent = this.getParent();
97
      if( parent.getUserData( "widgetSelectedListener" ) ) {
98
        var req = org.eclipse.swt.Request.getInstance();
99
        var wm = org.eclipse.swt.WidgetManager.getInstance();
100
        var id = wm.findIdByWidget( parent );
101
        var index = this.getUserData( "index" );
102
        req.addEvent( "org.eclipse.swt.events.widgetSelected", id );
103
        req.addEvent( "org.eclipse.swt.events.widgetSelected.index", index );
104
        req.send();
105
      }
106
    },
107
108
    _onKeyDown : function( evt ) {
109
      var keyId = evt.getKeyIdentifier();
110
      if ( keyId == "Enter" ) {
111
        var parent = this.getParent();
112
        if( parent.getUserData( "widgetSelectedListener" ) ) {
113
          var req = org.eclipse.swt.Request.getInstance();
114
          var wm = org.eclipse.swt.WidgetManager.getInstance();
115
          var id = wm.findIdByWidget( parent );
116
          var index = this.getUserData( "index" );
117
          req.addEvent( "org.eclipse.swt.events.widgetSelected", id );
118
          req.addEvent( "org.eclipse.swt.events.widgetSelected.index", index );
119
          req.send();
120
        }
121
      }
122
    },
123
124
    _onTabIndexChange : function( evt ) {
125
      var tabIndex = evt.getValue();
126
      if( tabIndex >= 0 ) {
127
        var target = evt.getCurrentTarget();
128
        var children = target.getChildren();
129
        for( var i = 0; i < children.length; i++ ) {
130
          child = children[ i ];
131
          child.setTabIndex( tabIndex++ );
132
        }
133
        target.setUserData( "nextTabIndex", tabIndex );
134
        target.setTabIndex( -1 );
135
      }
136
    }
137
  }
138
});
(-)js/org/eclipse/swt/widgets/Link.js (+326 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 Innoopract Informationssysteme GmbH. All rights reserved.
3
 * This program and the accompanying materials are made available under the
4
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
5
 * and is available at http://www.eclipse.org/legal/epl-v10.html
6
 *
7
 * Contributors: Innoopract Informationssysteme GmbH - initial API and
8
 * implementation
9
 ******************************************************************************/
10
11
/**
12
 * This class provides the client-side implementation for
13
 * org.eclipse.swt.widgets.Link
14
 */
15
qx.Class.define( "org.eclipse.swt.widgets.Link", {
16
  extend : qx.ui.layout.CanvasLayout,
17
18
  construct : function() {
19
    this.base( arguments );
20
    this.setAppearance( "link" );
21
    // Default values
22
    this._text = "";
23
    this._hasSelectionListener = false;
24
    this._hyperlinksHaveListeners = false;
25
    this._linkColor;
26
    // innerTab handling
27
    this._currentLinkFocused = -1;
28
    this._linksCount = 0;        
29
    //
30
    this._link = new qx.ui.embed.HtmlEmbed();
31
    this._link.setAppearance( "link-text" );
32
    this.add( this._link );
33
    //
34
    this.setHideFocus( true );
35
    //
36
    this.__onMouseDown = qx.lang.Function.bindEvent( this._onMouseDown, this );
37
    this.__onKeyDown = qx.lang.Function.bindEvent( this._onKeyDown, this );
38
    //
39
    this.addEventListener( "appear", this._onAppear, this );
40
    this.addEventListener( "changeEnabled", this._onChangeEnabled, this );
41
    this.addEventListener( "contextmenu", this._onContextMenu, this );
42
    // Event listener used for inner TabIndex change
43
    this.addEventListener( "keypress", this._onKeyPress );
44
    this.addEventListener( "focusout", this._onFocusOut );
45
    //
46
    this._link.addEventListener( "changeHtml", this._onChangeHtml, this );
47
  },
48
49
  destruct : function() {
50
    this._removeEventListeners();
51
    delete this.__onMouseDown;
52
    delete this.__onKeyDown;
53
    this.removeEventListener( "appear", this._onAppear, this );
54
    this.removeEventListener( "contextmenu", this._onContextMenu, this );
55
    this.removeEventListener( "changeEnabled", this._onChangeEnabled, this );
56
    this.removeEventListener( "keypress", this._onKeyPress );
57
    this.removeEventListener( "focusout", this._onFocusOut );
58
    this._link.removeEventListener( "changeHtml", this._onChangeHtml, this );
59
    this._link.dispose();
60
  },
61
62
  members : {
63
    _onContextMenu : function( evt ) {
64
      var menu = this.getContextMenu();
65
      if( menu != null ) {
66
        menu.setLocation( evt.getPageX(), evt.getPageY() );
67
        menu.setOpener( this );
68
        menu.show();
69
        evt.stopPropagation();
70
      }
71
    },
72
    
73
  	_onAppear : function( evt ) {
74
      this._link.setTabIndex( -1 );
75
      this._link.setHideFocus( true );
76
      this._applyHyperlinksStyleProperties();
77
      this._addEventListeners();
78
  	},
79
  	
80
  	_onChangeHtml : function( evt ) {
81
      this._applyHyperlinksStyleProperties();
82
      this._addEventListeners();
83
  	},
84
  	
85
  	_applyTextColor : function( value, old ) {
86
      this.base( arguments, value, old );
87
      var themeValues 
88
        = new org.eclipse.swt.theme.ThemeValues( this._getStates() );
89
      this._linkColor = themeValues.getCssColor( "Link-Hyperlink", "color" );
90
      themeValues.dispose();
91
      this._applyHyperlinksStyleProperties();
92
  	},
93
  	
94
  	_onChangeEnabled : function( evt ) {      
95
      this._applyHyperlinksStyleProperties();
96
  	},
97
  	
98
  	_getStates : function() {
99
      if( !this.__states ) {
100
        this.__states = {};
101
      }
102
      return this.__states;
103
  	},
104
    
105
    addState : function( state ) {
106
      this.base( arguments, state );
107
      this._link.addState( state );
108
    },
109
    
110
    removeState : function( state ) {
111
      this.base( arguments, state );
112
      this._link.removeState( state );
113
    },
114
115
    setHasSelectionListener : function( value ) {
116
      this._hasSelectionListener = value;
117
    },
118
       
119
    addText : function( text ) {
120
      this._text += text;
121
    },
122
123
    addLink : function( text, index ) {
124
      this._text += "<span tabIndex=\"1\" ";
125
      this._text += "style=\"";
126
      this._text += "text-decoration:underline; ";
127
      this._text += "\" ";
128
      this._text += "id=\"" + index + "\"";
129
      this._text += ">";
130
      this._text += text;
131
      this._text += "</span>";
132
      this._linksCount++;
133
    },
134
    
135
    applyText : function() {
136
      this._link.setHtml( this._text );
137
      if ( this._linksCount == 0 ) {
138
        this.setTabIndex( -1 );
139
      } else {
140
        this.setTabIndex( 1 );
141
      }
142
    },
143
    
144
    clear : function() {
145
      this._removeEventListeners();
146
      this._text = "";
147
      this._linksCount = 0;
148
    },
149
    
150
    _applyHyperlinksStyleProperties : function() {
151
      var linkElement = this.getElement();
152
      if( linkElement ) {
153
        var hyperlinks = linkElement.getElementsByTagName( "span" );
154
        for( i = 0; i < hyperlinks.length; i++ ) {
155
          if( this._linkColor ) {
156
            if( this.isEnabled() ) {
157
      	      hyperlinks[ i ].style.color = this._linkColor;
158
            } else {
159
              hyperlinks[ i ].style.color = "";
160
            }  
161
      	  }
162
      	  if( this.isEnabled() ) {
163
      	  	hyperlinks[ i ].style.cursor = "pointer";
164
      	  } else {
165
      	  	hyperlinks[ i ].style.cursor = "default";
166
      	  }
167
        }
168
      }
169
    },
170
    
171
    _addEventListeners : function() {
172
      var linkElement = this.getElement();
173
      if( linkElement && !this._hyperlinksHaveListeners ) {
174
        var hyperlinks = linkElement.getElementsByTagName( "span" );
175
        for( i = 0; i < hyperlinks.length; i++ ) {
176
          qx.html.EventRegistration.addEventListener( hyperlinks[ i ], 
177
                                                      "mousedown", 
178
                                                      this.__onMouseDown );
179
          qx.html.EventRegistration.addEventListener( hyperlinks[ i ], 
180
                                                      "keydown", 
181
                                                      this.__onKeyDown );
182
        }
183
        this._hyperlinksHaveListeners = true;
184
      }
185
    },
186
    
187
    _removeEventListeners : function() {
188
      var linkElement = this.getElement();
189
      if( linkElement && this._hyperlinksHaveListeners ) {
190
        var hyperlinks = linkElement.getElementsByTagName( "span" );
191
        for( i = 0; i < hyperlinks.length; i++ ) {
192
          qx.html.EventRegistration.removeEventListener( hyperlinks[ i ], 
193
                                                         "mousedown", 
194
                                                         this.__onMouseDown );
195
          qx.html.EventRegistration.removeEventListener( hyperlinks[ i ], 
196
                                                         "keydown", 
197
                                                         this.__onKeyDown );
198
        }
199
        this._hyperlinksHaveListeners = false;
200
      }
201
    },
202
    
203
    _onMouseDown : function( e ) {
204
      var target = this._getEventTarget( e );
205
      var index = target.id;
206
      this._currentLinkFocused = index;
207
      target.focus();
208
      var leftBtnPressed = this._isLeftMouseButtonPressed( e );
209
      if( this.isEnabled() && leftBtnPressed ) {
210
        this._sendChanges( index );
211
      }
212
    },
213
    
214
    _isLeftMouseButtonPressed : function( e ) {
215
      var leftBtnPressed;
216
      if( e.which ) {
217
        leftBtnPressed = ( e.which == 1 );
218
      } else if ( e.button ) {
219
        if( qx.core.Variant.isSet( "qx.client", "mshtml" ) ) {
220
          leftBtnPressed = ( e.button == 1 );
221
        } else {
222
          leftBtnPressed = ( e.button == 0 );
223
        }
224
      }
225
      return leftBtnPressed;
226
    },
227
    
228
    _onKeyDown : function( e ) {
229
      if( this.isEnabled() && e.keyCode == 13 ) {
230
        var target = this._getEventTarget( e );
231
        var index = target.id;
232
        this._sendChanges( index );
233
      }
234
    },
235
    
236
    _getEventTarget : function( e ) {
237
      var target;
238
      if( qx.core.Variant.isSet( "qx.client", "mshtml" ) ) {
239
        target = window.event.srcElement;
240
      } else {
241
        target = e.target;
242
      }
243
      return target;
244
    },
245
    
246
    // Override of the _ontabfocus method from qx.ui.core.Widget 
247
    _ontabfocus : function() {
248
      if( this._currentLinkFocused == -1 && this._linksCount > 0 ) {
249
        var linkElement = this.getElement();
250
        if( linkElement ) {
251
          var hyperlinks = linkElement.getElementsByTagName( "span" );
252
          hyperlinks[ 0 ].focus();
253
          this._currentLinkFocused = 0;
254
        }
255
      }
256
    },
257
    
258
    _onKeyPress : function( evt ) {
259
      if(    this.isFocused() 
260
          && evt.getKeyIdentifier() == "Tab" 
261
          && this._linksCount > 0 )
262
      {
263
        if(    !evt.isShiftPressed()
264
            && this._currentLinkFocused >= 0
265
            && this._currentLinkFocused < ( this._linksCount - 1 ) )
266
        {
267
          evt.stopPropagation();
268
          evt.preventDefault();
269
          this._currentLinkFocused++;
270
          this._focusLinkByID( this._currentLinkFocused );
271
        } else if(    !evt.isShiftPressed()
272
                   && this._currentLinkFocused == -1 )
273
        {
274
          evt.stopPropagation();
275
          evt.preventDefault();
276
          var linkElement = this.getElement();
277
          if( linkElement ) {
278
            var hyperlinks = linkElement.getElementsByTagName( "span" );
279
            hyperlinks[ 0 ].focus();
280
            this._currentLinkFocused = 0;
281
          }
282
        } else if(    evt.isShiftPressed()
283
                   && this._currentLinkFocused > 0
284
                   && this._currentLinkFocused <= ( this._linksCount - 1 ) )
285
        {
286
          evt.stopPropagation();
287
          evt.preventDefault();
288
          this._currentLinkFocused--;
289
          this._focusLinkByID( this._currentLinkFocused );
290
        }    
291
      }
292
    },
293
    
294
    _focusLinkByID : function( id ) {
295
      var linkElement = this.getElement();
296
      if( linkElement ) {
297
        var hyperlinks = linkElement.getElementsByTagName( "span" );
298
        hyperlinks[ id ].focus();
299
      }
300
    },
301
    
302
    _onFocusOut : function( evt ) {
303
      var linkElement = this.getElement();
304
      if( linkElement ) {
305
        var hyperlinks = linkElement.getElementsByTagName( "span" );
306
        if( this._currentLinkFocused >= 0 ) {
307
          hyperlinks[ this._currentLinkFocused ].blur();
308
        }
309
      }
310
      this._currentLinkFocused = -1;
311
    },
312
    
313
    _sendChanges : function( index ) {
314
      if( !org_eclipse_rap_rwt_EventUtil_suspend ) {
315
        var widgetManager = org.eclipse.swt.WidgetManager.getInstance();
316
        var id = widgetManager.findIdByWidget( this );
317
        var req = org.eclipse.swt.Request.getInstance();
318
        if( this._hasSelectionListener ) {
319
          req.addEvent( "org.eclipse.swt.events.widgetSelected", id );
320
          req.addEvent( "org.eclipse.swt.events.widgetSelected.index", index );
321
          req.send();
322
        }
323
      }
324
    }
325
  }
326
} );
(-)src/org/eclipse/swt/widgets/Link.java (-12 / +30 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2002, 2008 Innoopract Informationssysteme GmbH.
2
 * Copyright (c) 2002, 2009 Innoopract Informationssysteme GmbH.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 35-40 Link Here
35
 * @since 1.0
35
 * @since 1.0
36
 */
36
 */
37
public class Link extends Control {
37
public class Link extends Control {
38
  
39
  //Must be kept in sync with appearance value in AppearancesBase.js
40
  private final static int PADDING = 2;
38
41
39
  private String text = "";
42
  private String text = "";
40
  private String displayText = "";
43
  private String displayText = "";
Lines 180-195 Link Here
180
    SelectionEvent.removeListener( this, listener );
183
    SelectionEvent.removeListener( this, listener );
181
  }
184
  }
182
185
183
  public Point computeSize( final int wHint, final int hHint, final boolean changed ) {
186
  public Point computeSize( final int wHint, 
187
                            final int hHint, 
188
                            final boolean changed ) {
184
    checkWidget();
189
    checkWidget();
185
    int width = 0;
190
    int width = 0;
186
    int height = 0;
191
    int height = 0;
187
    int border = getBorderWidth();
192
    int border = getBorderWidth();
188
    if( ( displayText.length() > 0 ) ) {
193
    if( ( displayText.length() > 0 ) ) {
189
      // TODO [rst] change to textExtent when wrap supported
194
      // Replace '&' with '&&' to ensure proper size calculation with one '&',
190
      Point extent = TextSizeDetermination.stringExtent( getFont(), displayText );
195
      // because the other will be escaped in 
196
      // TextSizeDetermination#createMeasureString()
197
      String string = escapeAmpersand( displayText );
198
      Point extent = TextSizeDetermination.textExtent( getFont(), 
199
                                                       string, 
200
                                                       wHint );
191
      width = extent.x;
201
      width = extent.x;
192
      height = extent.y + 2;
202
      height = extent.y;
193
    }
203
    }
194
    if( wHint != SWT.DEFAULT ) {
204
    if( wHint != SWT.DEFAULT ) {
195
      width = wHint;
205
      width = wHint;
Lines 197-210 Link Here
197
    if( hHint != SWT.DEFAULT ) {
207
    if( hHint != SWT.DEFAULT ) {
198
      height = hHint;
208
      height = hHint;
199
    }
209
    }
200
    width += border * 2;
210
    width += border * 2 + PADDING * 2;
201
    height += border * 2;
211
    height += border * 2 + PADDING * 2;
202
    return new Point( width, height );
212
    return new Point( width, height );
203
  }
213
  }
204
214
  
205
  public int getBorderWidth() {
215
  private static String escapeAmpersand( final String string ) {
206
	// TODO: [rst] why overriding control#getBorderWidth
216
    int index = 0;
207
    return ( ( style & SWT.BORDER ) != 0 ) ? 1 : 0;
217
    StringBuffer result = new StringBuffer();
218
    for( int i = 0; i < string.length(); i++ ) {
219
      if( string.charAt( i ) == '&' ) {
220
        result.append( "&&" );
221
      } else {
222
        result.append( string.charAt( i ) );
223
      }
224
    }
225
    return result.toString();
208
  }
226
  }
209
227
210
  public Object getAdapter( final Class adapter ) {
228
  public Object getAdapter( final Class adapter ) {
Lines 229-235 Link Here
229
    }
247
    }
230
    return result;
248
    return result;
231
  }
249
  }
232
250
  
233
  boolean isTabGroup() {
251
  boolean isTabGroup() {
234
    return true;
252
    return true;
235
  }
253
  }
(-)src/org/eclipse/swt/internal/widgets/linkkit/Link.theme.xml (+3 lines)
Lines 32-37 Link Here
32
      <property name="color"
32
      <property name="color"
33
          type="color"
33
          type="color"
34
          description="Text color for hyperlinks in Link widget." />
34
          description="Text color for hyperlinks in Link widget." />
35
      
36
      <state name="disabled"
37
          description="Applies to hyperlinks of a disabled Link widget." />
35
38
36
    </element>
39
    </element>
37
40
(-)src/org/eclipse/rap/demo/controls/LinkTab.java (-6 / +39 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2007, 2008 Innoopract Informationssysteme GmbH.
2
 * Copyright (c) 2007, 2009 Innoopract Informationssysteme GmbH.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 14-27 Link Here
14
import org.eclipse.jface.dialogs.MessageDialog;
14
import org.eclipse.jface.dialogs.MessageDialog;
15
import org.eclipse.swt.SWT;
15
import org.eclipse.swt.SWT;
16
import org.eclipse.swt.custom.CTabFolder;
16
import org.eclipse.swt.custom.CTabFolder;
17
import org.eclipse.swt.events.SelectionAdapter;
17
import org.eclipse.swt.events.*;
18
import org.eclipse.swt.events.SelectionEvent;
18
import org.eclipse.swt.graphics.Point;
19
import org.eclipse.swt.layout.GridLayout;
19
import org.eclipse.swt.layout.*;
20
import org.eclipse.swt.widgets.*;
20
import org.eclipse.swt.widgets.*;
21
21
22
public class LinkTab extends ExampleTab {
22
public class LinkTab extends ExampleTab {
23
  
24
  private static final String PROP_CONTEXT_MENU = "contextMenu";
23
25
26
  private Link link1;
24
  private Link customLink;
27
  private Link customLink;
28
  private Link fixedSizeLink;
25
29
26
  public LinkTab( final CTabFolder topFolder ) {
30
  public LinkTab( final CTabFolder topFolder ) {
27
    super( topFolder, "Link" );
31
    super( topFolder, "Link" );
Lines 36-52 Link Here
36
    createBgImageButton();
40
    createBgImageButton();
37
    createFontChooser();
41
    createFontChooser();
38
    createCustomLinkControl( parent );
42
    createCustomLinkControl( parent );
43
    createPropertyCheckbox( "Add Context Menu On First Link", 
44
                            PROP_CONTEXT_MENU );
39
  }
45
  }
40
46
41
  protected void createExampleControls( final Composite parent ) {
47
  protected void createExampleControls( final Composite parent ) {
42
    parent.setLayout( new GridLayout() );
48
    parent.setLayout( new GridLayout() );
43
    int style = getStyle();
49
    int style = getStyle();
44
    Link link1 = new Link( parent, style );
50
    link1 = new Link( parent, style );
51
//    link1.setText( "Lorem <a>ipsum</a> dolor sit amet" );
52
//    link1.setEnabled( false );
53
//    link1.setVisible( false );
45
    link1.setText( "Lorem <a>ipsum</a> dolor <a>sit amet</a>" );
54
    link1.setText( "Lorem <a>ipsum</a> dolor <a>sit amet</a>" );
55
    link1.addSelectionListener( new SelectionAdapter() {
56
      public void widgetSelected( final SelectionEvent event ) {
57
        String msg = "Link widget selected, text=" + event.text;
58
        MessageDialog.openInformation( getShell(), "Information", msg );
59
      }
60
    } );
61
    if( hasCreateProperty( PROP_CONTEXT_MENU ) ) {
62
      Menu linkMenu = new Menu( link1 );
63
      MenuItem linkMenuItem = new MenuItem( linkMenu, SWT.PUSH );
64
      linkMenuItem.addSelectionListener( new SelectionAdapter() {
65
        public void widgetSelected( final SelectionEvent event ) {
66
          String message = "You requested a context menu for the Link";
67
          MessageDialog.openInformation( link1.getShell(),
68
                                         "Information",
69
                                         message );
70
       }
71
      } );
72
      linkMenuItem.setText( "Link context menu item" );
73
      link1.setMenu( linkMenu );
74
    }
46
    Link link2 = new Link( parent, style );
75
    Link link2 = new Link( parent, style );
47
    link2.setText( "Link without href" );
76
    link2.setText( "Link without href" );
48
    Link link3 = new Link( parent, style );
77
    Link link3 = new Link( parent, style );
49
    link3.setText( "<a>Link with one href</a>" );
78
    link3.setText( "<a>Link with one href \"&&<>\\\"</a>" );
50
    customLink = new Link( parent, style );
79
    customLink = new Link( parent, style );
51
    customLink.setText( "Custom link, use controls to your right to change" );
80
    customLink.setText( "Custom link, use controls to your right to change" );
52
    customLink.addSelectionListener( new SelectionAdapter() {
81
    customLink.addSelectionListener( new SelectionAdapter() {
Lines 55-64 Link Here
55
        MessageDialog.openInformation( getShell(), "Information", msg );
84
        MessageDialog.openInformation( getShell(), "Information", msg );
56
      }
85
      }
57
    } );
86
    } );
87
    fixedSizeLink = new Link( parent, style );
88
    fixedSizeLink.setText( "Fixed size Link with some very long text <a>that should be wrapped.</a>" );
89
    fixedSizeLink.setLayoutData( new GridData( 100, 100 ) );
58
    registerControl( link1 );
90
    registerControl( link1 );
59
    registerControl( link2 );
91
    registerControl( link2 );
60
    registerControl( link3 );
92
    registerControl( link3 );
61
    registerControl( customLink );
93
    registerControl( customLink );
94
    registerControl( fixedSizeLink );
62
  }
95
  }
63
96
64
  private void createCustomLinkControl( final Composite parent ) {
97
  private void createCustomLinkControl( final Composite parent ) {
(-)src/org/eclipse/rap/demo/controls/VariantsTab.java (+9 lines)
Lines 40-45 Link Here
40
40
41
  private Button myButton;
41
  private Button myButton;
42
  private Label myLabel;
42
  private Label myLabel;
43
  private Link myLink;
43
  private Text myText;
44
  private Text myText;
44
  private List myList;
45
  private List myList;
45
  private Tree myTree;
46
  private Tree myTree;
Lines 81-86 Link Here
81
    myLabel.setText( "Customized Label" );
82
    myLabel.setText( "Customized Label" );
82
    myLabel.setData( WidgetUtil.CUSTOM_VARIANT, getVariant() );
83
    myLabel.setData( WidgetUtil.CUSTOM_VARIANT, getVariant() );
83
    registerControl( myLabel );
84
    registerControl( myLabel );
85
    
86
    // myLink
87
    myLink = new Link( parent, style );
88
    myLink.setLayoutData( new GridData( GridData.FILL_HORIZONTAL ) );
89
    myLink.setText( "Customized <a>Link</a>" );
90
    myLink.setData( WidgetUtil.CUSTOM_VARIANT, getVariant() );
91
    registerControl( myLink );
84
92
85
    // myText
93
    // myText
86
    myText = new Text( parent, style );
94
    myText = new Text( parent, style );
Lines 149-154 Link Here
149
  private void setCustomVariant( final String variant ) {
157
  private void setCustomVariant( final String variant ) {
150
    myButton.setData( WidgetUtil.CUSTOM_VARIANT, variant );
158
    myButton.setData( WidgetUtil.CUSTOM_VARIANT, variant );
151
    myLabel.setData( WidgetUtil.CUSTOM_VARIANT, variant );
159
    myLabel.setData( WidgetUtil.CUSTOM_VARIANT, variant );
160
    myLink.setData( WidgetUtil.CUSTOM_VARIANT, variant );
152
    myText.setData( WidgetUtil.CUSTOM_VARIANT, variant );
161
    myText.setData( WidgetUtil.CUSTOM_VARIANT, variant );
153
    myList.setData( WidgetUtil.CUSTOM_VARIANT, variant );
162
    myList.setData( WidgetUtil.CUSTOM_VARIANT, variant );
154
    myTree.setData( WidgetUtil.CUSTOM_VARIANT, variant );
163
    myTree.setData( WidgetUtil.CUSTOM_VARIANT, variant );
(-)theme1/theme.css (+8 lines)
Lines 416-421 Link Here
416
  padding: 10px;
416
  padding: 10px;
417
}
417
}
418
418
419
Link-Hyperlink.special-red {
420
  color: #ffaaaa;
421
}
422
423
Link-Hyperlink.special-blue {
424
  color: #aaaaff;
425
}
426
419
Button[PUSH].special-red, Button[TOGGLE].special-red {
427
Button[PUSH].special-red, Button[TOGGLE].special-red {
420
  border: 2px solid red;
428
  border: 2px solid red;
421
}
429
}
(-)src/org/eclipse/swt/internal/widgets/linkkit/LinkLCA_Test.java (-8 / +9 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2002, 2008 Innoopract Informationssysteme GmbH.
2
 * Copyright (c) 2002, 2009 Innoopract Informationssysteme GmbH.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 33-44 Link Here
33
    Display display = new Display();
33
    Display display = new Display();
34
    Composite shell = new Shell( display, SWT.NONE );
34
    Composite shell = new Shell( display, SWT.NONE );
35
    Link link = new Link( shell, SWT.NONE );
35
    Link link = new Link( shell, SWT.NONE );
36
    Boolean hasListeners;
37
    RWTFixture.markInitialized( display );
36
    RWTFixture.markInitialized( display );
38
    RWTFixture.preserveWidgets();
37
    RWTFixture.preserveWidgets();
39
    IWidgetAdapter adapter = WidgetUtil.getAdapter( link );
38
    IWidgetAdapter adapter = WidgetUtil.getAdapter( link );
40
    hasListeners = ( Boolean )adapter.getPreserved( LinkLCA.PROP_SEL_LISTENER );
41
    assertEquals( "", adapter.getPreserved( Props.TEXT ) );
39
    assertEquals( "", adapter.getPreserved( Props.TEXT ) );
40
    Boolean hasListeners
41
      = ( Boolean )adapter.getPreserved( Props.SELECTION_LISTENERS );
42
    assertEquals( Boolean.FALSE, hasListeners );
42
    assertEquals( Boolean.FALSE, hasListeners );
43
    RWTFixture.clearPreserved();
43
    RWTFixture.clearPreserved();
44
    link.setText( "some text" );
44
    link.setText( "some text" );
Lines 52-59 Link Here
52
    } );
52
    } );
53
    RWTFixture.preserveWidgets();
53
    RWTFixture.preserveWidgets();
54
    adapter = WidgetUtil.getAdapter( link );
54
    adapter = WidgetUtil.getAdapter( link );
55
    hasListeners = ( Boolean )adapter.getPreserved( LinkLCA.PROP_SEL_LISTENER );
56
    assertEquals( "some text", adapter.getPreserved( Props.TEXT ) );
55
    assertEquals( "some text", adapter.getPreserved( Props.TEXT ) );
56
    hasListeners
57
      = ( Boolean )adapter.getPreserved( Props.SELECTION_LISTENERS );
57
    assertEquals( Boolean.TRUE, hasListeners );
58
    assertEquals( Boolean.TRUE, hasListeners );
58
    RWTFixture.clearPreserved();
59
    RWTFixture.clearPreserved();
59
    //control: enabled
60
    //control: enabled
Lines 235-244 Link Here
235
    LinkLCA lca = new LinkLCA();
236
    LinkLCA lca = new LinkLCA();
236
    lca.renderChanges( link );
237
    lca.renderChanges( link );
237
    String markup = Fixture.getAllMarkup();
238
    String markup = Fixture.getAllMarkup();
238
    assertContains( "LinkUtil.clear( w )", markup );
239
    assertContains( "clear()", markup );
239
    assertContains( "LinkUtil.addText( w, \"Big \" )", markup );
240
    assertContains( "addText( \"Big \" )", markup );
240
    assertContains( "LinkUtil.addLink( w, \"&lt;b&gt;Bang&lt;/b&gt;\", 0 )",
241
    assertContains( "addLink( \"&lt;b&gt;Bang&lt;/b&gt;\", 0 )", markup );
241
                    markup );
242
    assertContains( "applyText()", markup );
242
  }
243
  }
243
244
244
  public void testEscape() throws Exception {
245
  public void testEscape() throws Exception {

Return to bug 275117