Skip to content
Browse files

Commit of Advanced UI sample

  • Loading branch information...
1 parent 143638b commit 4caa4d40c8946fff4e70dbe95b335f2a1e6be699 Tim Windsor committed Dec 9, 2011
Showing with 6,525 additions and 0 deletions.
  1. +6 −0 Advanced UI/.classpath
  2. +2 −0 Advanced UI/.gitignore
  3. +29 −0 Advanced UI/.project
  4. +12 −0 Advanced UI/.settings/org.eclipse.jdt.core.prefs
  5. +18 −0 Advanced UI/BlackBerry_App_Descriptor.xml
  6. +45 −0 Advanced UI/README.md
  7. +92 −0 Advanced UI/src/com/samples/toolkit/ui/FieldDimensionUtilities.java
  8. +112 −0 Advanced UI/src/com/samples/toolkit/ui/component/BaseButtonField.java
  9. +95 −0 Advanced UI/src/com/samples/toolkit/ui/component/BitmapButtonField.java
  10. +331 −0 Advanced UI/src/com/samples/toolkit/ui/component/BitmapGaugeField.java
  11. +495 −0 Advanced UI/src/com/samples/toolkit/ui/component/BitmapSliderField.java
  12. +48 −0 Advanced UI/src/com/samples/toolkit/ui/component/ColoredLabelField.java
  13. +187 −0 Advanced UI/src/com/samples/toolkit/ui/component/EmbossedButtonField.java
  14. +164 −0 Advanced UI/src/com/samples/toolkit/ui/component/HyperlinkButtonField.java
  15. +243 −0 Advanced UI/src/com/samples/toolkit/ui/component/LabeledSwitch.java
  16. +312 −0 Advanced UI/src/com/samples/toolkit/ui/component/ListStyleButtonField.java
  17. +236 −0 Advanced UI/src/com/samples/toolkit/ui/component/PillButtonField.java
  18. +88 −0 Advanced UI/src/com/samples/toolkit/ui/component/ProgressAnimationField.java
  19. +293 −0 Advanced UI/src/com/samples/toolkit/ui/component/RatingField.java
  20. +480 −0 Advanced UI/src/com/samples/toolkit/ui/component/SliderField.java
  21. +179 −0 Advanced UI/src/com/samples/toolkit/ui/component/SwitchField.java
  22. +85 −0 Advanced UI/src/com/samples/toolkit/ui/container/EvenlySpacedHorizontalFieldManager.java
  23. +90 −0 Advanced UI/src/com/samples/toolkit/ui/container/EvenlySpacedVerticalFieldManager.java
  24. +54 −0 Advanced UI/src/com/samples/toolkit/ui/container/GridFlowFieldManager.java
  25. +137 −0 Advanced UI/src/com/samples/toolkit/ui/container/HorizontalButtonFieldSet.java
  26. +50 −0 Advanced UI/src/com/samples/toolkit/ui/container/HorizontalListStyleButtonSet.java
  27. +119 −0 Advanced UI/src/com/samples/toolkit/ui/container/JustifiedEvenlySpacedHorizontalFieldManager.java
  28. +165 −0 Advanced UI/src/com/samples/toolkit/ui/container/JustifiedHorizontalFieldManager.java
  29. +125 −0 Advanced UI/src/com/samples/toolkit/ui/container/JustifiedVerticalFieldManager.java
  30. +68 −0 Advanced UI/src/com/samples/toolkit/ui/container/ListStyleButtonSet.java
  31. +126 −0 Advanced UI/src/com/samples/toolkit/ui/container/NegativeMarginHorizontalFieldManager.java
  32. +128 −0 Advanced UI/src/com/samples/toolkit/ui/container/NegativeMarginVerticalFieldManager.java
  33. +82 −0 Advanced UI/src/com/samples/toolkit/ui/container/PillButtonSet.java
  34. +169 −0 Advanced UI/src/com/samples/toolkit/ui/container/TwoColumnField.java
  35. +125 −0 Advanced UI/src/com/samples/toolkit/ui/container/TwoColumnFieldManager.java
  36. +100 −0 Advanced UI/src/com/samples/toolkit/ui/container/VerticalButtonFieldSet.java
  37. +39 −0 Advanced UI/src/com/samples/toolkit/ui/test/ForegroundManager.java
  38. +36 −0 Advanced UI/src/com/samples/toolkit/ui/test/UIExampleApplication.java
  39. +122 −0 Advanced UI/src/com/samples/toolkit/ui/test/UIExampleBitmapButtonScreen.java
  40. +125 −0 Advanced UI/src/com/samples/toolkit/ui/test/UIExampleButtonScreen.java
  41. +125 −0 Advanced UI/src/com/samples/toolkit/ui/test/UIExampleButtonSetScreen.java
  42. +72 −0 Advanced UI/src/com/samples/toolkit/ui/test/UIExampleGaugeScreen.java
  43. +59 −0 Advanced UI/src/com/samples/toolkit/ui/test/UIExampleHyperlinkScreen.java
  44. +181 −0 Advanced UI/src/com/samples/toolkit/ui/test/UIExampleIndexScreen.java
  45. +60 −0 Advanced UI/src/com/samples/toolkit/ui/test/UIExampleLabeledSwitchScreen.java
  46. +72 −0 Advanced UI/src/com/samples/toolkit/ui/test/UIExampleListStyleButtonFieldScreen.java
  47. +76 −0 Advanced UI/src/com/samples/toolkit/ui/test/UIExampleListStyleButtonSetScreen.java
  48. +84 −0 Advanced UI/src/com/samples/toolkit/ui/test/UIExampleNegativeMarginScreen.java
  49. +127 −0 Advanced UI/src/com/samples/toolkit/ui/test/UIExamplePillButtonScreen.java
  50. +59 −0 Advanced UI/src/com/samples/toolkit/ui/test/UIExampleProgressAnimationScreen.java
  51. +101 −0 Advanced UI/src/com/samples/toolkit/ui/test/UIExampleRatingScreen.java
  52. +47 −0 Advanced UI/src/com/samples/toolkit/ui/test/UIExampleScreen.java
  53. +50 −0 Advanced UI/src/com/samples/toolkit/ui/test/UIExampleSliderScreen.java
View
6 Advanced UI/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/net.rim.ejde.BlackBerryVMInstallType/BlackBerry JRE 6.0.0"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
View
2 Advanced UI/.gitignore
@@ -0,0 +1,2 @@
+/bin
+/deliverables
View
29 Advanced UI/.project
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>Advanced UI</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>net.rim.ejde.internal.builder.BlackBerryPreprocessBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>net.rim.ejde.internal.builder.BlackBerryResourcesBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>net.rim.ejde.BlackBerryPreProcessNature</nature>
+ <nature>net.rim.ejde.BlackBerryProjectCoreNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
View
12 Advanced UI/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,12 @@
+#Thu Oct 27 17:27:21 EDT 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.4
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.3
View
18 Advanced UI/BlackBerry_App_Descriptor.xml
@@ -0,0 +1,18 @@
+<Properties ModelVersion="1.1.2">
+ <General Title="" Version="1.0.0" Vendor="BlackBerry Developer" Description=""/>
+ <Application Type="BlackBerry Application" MainMIDletName="" MainArgs="" HomeScreenPosition="0" StartupTier="7" IsSystemModule="false" IsAutostartup="false"/>
+ <Resources hasTitleResource="false" TitleResourceBundleName="" TitleResourceBundleRelativePath="" TitleResourceBundleClassName="" TitleResourceBundleKey="" DescriptionId="">
+ <Icons/>
+ </Resources>
+ <Compile OutputCompilerMessages="false" ConvertImages="false" CreateWarningForNoExportedRoutine="true" CompressResources="false" AliasList="">
+ <PreprocessorDefines/>
+ </Compile>
+ <Packaging OutputFileName="Advanced_UI" OutputFolder="deliverables" PreBuildStep="" PostBuildStep="" CleanStep="" GenerateALXFile="true">
+ <AlxFiles/>
+ </Packaging>
+ <HiddenProperties>
+ <ClassProtection/>
+ <PackageProtection/>
+ </HiddenProperties>
+ <AlternateEntryPoints/>
+</Properties>
View
45 Advanced UI/README.md
@@ -0,0 +1,45 @@
+# BlackBerry Advanced UI Samples
+
+The Graphics API provides features for working with images and painting, which together can be used to create custom UI components. The sample code provides a library of various custom components, including buttons, fields, and managers.
+
+For screenshots and sample images that can be used with the test application, please see this article: http://supportforums.blackberry.com/t5/Java-Development/Implement-advanced-buttons-fields-and-managers/ta-p/488276. The test images have not been open sourced or included in the repository.
+
+
+The sample code for this application is Open Source under the [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0.html).
+
+**Applies To**
+
+* [BlackBerry Java SDK for Smartphones](http://us.blackberry.com/developers/javaappdev/)
+
+
+**Author(s)**
+
+* [Tim Windsor](https://github.com/timwindsor)
+
+
+**Dependencies**
+
+1. BlackBerry Java SDK 4.2.0 or higher required.
+
+
+**Known Issues**
+
+1. The samples use the Preprocessor to gracefully degrade features on older software. Not all features will be exactly alike in all SDK versions.
+
+
+**To contribute code to this repository you must be [signed up as an official contributor](http://blackberry.github.com/howToContribute.html).**
+
+
+## Contributing Changes
+
+Please see the [README](https://github.com/blackberry/BlackBerry-Java) of the BlackBerry-Java repository for instructions on how to add new Samples or make modifications to existing Samples.
+
+
+## Bug Reporting and Feature Requests
+
+If you find a bug in a Sample, or have an enhancement request, simply file an [Issue](https://github.com/blackberry/BlackBerry-Java/issues) for the Sample and send a message (via github messages) to the Sample Author(s) to let them know that you have filed an [Issue](https://github.com/blackberry/BlackBerry-Java/issues).
+
+
+## Disclaimer
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
92 Advanced UI/src/com/samples/toolkit/ui/FieldDimensionUtilities.java
@@ -0,0 +1,92 @@
+//#preprocess
+
+/*
+* Copyright (c) 2011 Research In Motion Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.samples.toolkit.ui;
+
+import net.rim.device.api.ui.*;
+
+//#ifndef VER_4.1.0 | VER_4.2.0 | VER_4.2.1 | VER_4.3.0 | VER_4.5.0
+import net.rim.device.api.ui.decor.*;
+//#endif
+
+
+public class FieldDimensionUtilities
+{
+ private FieldDimensionUtilities() { }
+
+ public static int getBorderWidth( Field field )
+ {
+ int width = 0;
+
+ //#ifdef VER_4.1.0 | VER_4.2.0 | VER_4.2.1 | VER_4.3.0 | VER_4.5.0
+ width = field.getWidth() - field.getContentWidth() - field.getPaddingLeft() - field.getPaddingRight();
+ //#else
+ Border border = field.getBorder();
+ if( border != null ) {
+ width = border.getLeft() + border.getRight();
+ }
+ //#endif
+ return width;
+ }
+
+ public static int getBorderHeight( Field field )
+ {
+ int height = 0;
+
+ //#ifdef VER_4.1.0 | VER_4.2.0 | VER_4.2.1 | VER_4.3.0 | VER_4.5.0
+ height = field.getWidth() - field.getContentHeight() - field.getPaddingTop() - field.getPaddingBottom();
+ //#else
+ Border border = field.getBorder();
+ if( border != null ) {
+ height = border.getTop() + border.getBottom();
+ }
+ //#endif
+ return height;
+ }
+
+ public static int getBorderAndPaddingWidth( Field field )
+ {
+ int width = 0;
+ //#ifdef VER_4.1.0 | VER_4.2.0 | VER_4.2.1 | VER_4.3.0 | VER_4.5.0
+ width = field.getWidth() - field.getContentWidth();
+ //#else
+ width = field.getPaddingLeft() + field.getPaddingRight();
+ Border border = field.getBorder();
+ if( border != null ) {
+ width += border.getLeft() + border.getRight();
+ }
+ //#endif
+ return width;
+ }
+
+ public static int getBorderAndPaddingHeight( Field field )
+ {
+ int height = 0;
+ //#ifdef VER_4.1.0 | VER_4.2.0 | VER_4.2.1 | VER_4.3.0 | VER_4.5.0
+ height = field.getHeight() - field.getContentHeight();
+ //#else
+ height = field.getPaddingTop() + field.getPaddingBottom();
+ Border border = field.getBorder();
+ if( border != null ) {
+ height += border.getTop() + border.getBottom();
+ }
+ //#endif
+ return height;
+ }
+
+}
View
112 Advanced UI/src/com/samples/toolkit/ui/component/BaseButtonField.java
@@ -0,0 +1,112 @@
+/*
+* Copyright (c) 2011 Research In Motion Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.samples.toolkit.ui.component;
+
+import net.rim.device.api.system.*;
+import net.rim.device.api.ui.*;
+
+
+/**
+ * Implements all the stuff we don't want to do each time we need a new button
+ */
+public abstract class BaseButtonField extends Field
+{
+ private XYRect _drawFocusTempRect = new XYRect();
+
+ public BaseButtonField()
+ {
+ this( 0 );
+ }
+
+ public BaseButtonField( long style )
+ {
+ super( Field.FOCUSABLE | style );
+ }
+
+ protected void layout( int width, int height )
+ {
+ setExtent( 10, 10 );
+ }
+
+ protected void drawFocus( Graphics g, boolean on )
+ {
+ getFocusRect( _drawFocusTempRect );
+
+ boolean oldDrawStyleFocus = g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS );
+ boolean notEmpty = g.pushContext( _drawFocusTempRect.x, _drawFocusTempRect.y, _drawFocusTempRect.width, _drawFocusTempRect.height, 0, 0 );
+
+ try {
+ if( notEmpty ) {
+ g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, on );
+ paintBackground( g );
+ paint( g );
+ }
+ } finally {
+ g.popContext();
+ g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, oldDrawStyleFocus );
+ }
+ }
+
+ protected boolean keyChar( char character, int status, int time )
+ {
+ if( character == Characters.ENTER ) {
+ clickButton();
+ return true;
+ }
+ return super.keyChar( character, status, time );
+ }
+
+ protected boolean navigationClick( int status, int time )
+ {
+ clickButton();
+ return true;
+ }
+
+ protected boolean trackwheelClick( int status, int time )
+ {
+ clickButton();
+ return true;
+ }
+
+ protected boolean invokeAction( int action )
+ {
+ switch( action ) {
+ case ACTION_INVOKE: {
+ clickButton();
+ return true;
+ }
+ }
+ return super.invokeAction( action );
+ }
+
+ public void setDirty( boolean dirty ) {
+ // We never want to be dirty or muddy
+ }
+
+ public void setMuddy( boolean muddy ) {
+ // We never want to be dirty or muddy
+ }
+
+ /**
+ * A public way to click this button
+ */
+ public void clickButton()
+ {
+ fieldChangeNotify( 0 );
+ }
+}
+
View
95 Advanced UI/src/com/samples/toolkit/ui/component/BitmapButtonField.java
@@ -0,0 +1,95 @@
+/*
+* Copyright (c) 2011 Research In Motion Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.samples.toolkit.ui.component;
+
+import net.rim.device.api.system.*;
+import net.rim.device.api.ui.*;
+
+public class BitmapButtonField extends BaseButtonField
+{
+ private Bitmap[] _bitmaps;
+ private static final int NORMAL = 0;
+ private static final int FOCUS = 1;
+
+ public BitmapButtonField( Bitmap normalState )
+ {
+ this( normalState, normalState, 0 );
+ }
+
+ public BitmapButtonField( Bitmap normalState, Bitmap focusState )
+ {
+ this( normalState, focusState, 0 );
+ }
+
+ public BitmapButtonField( Bitmap normalState, Bitmap focusState, long style )
+ {
+ super( Field.FOCUSABLE | style );
+
+ if( (normalState.getWidth() != focusState.getWidth())
+ || (normalState.getHeight() != focusState.getHeight()) ){
+
+ throw new IllegalArgumentException( "Image sizes don't match" );
+ }
+
+ _bitmaps = new Bitmap[] { normalState, focusState };
+ }
+
+ public void setImage( Bitmap normalState ){
+ _bitmaps[NORMAL] = normalState;
+ invalidate();
+ }
+
+ public void setFocusImage( Bitmap focusState ){
+ _bitmaps[FOCUS] = focusState;
+ invalidate();
+ }
+
+ public int getPreferredWidth() {
+ return _bitmaps[NORMAL].getWidth();
+ }
+
+ public int getPreferredHeight() {
+ return _bitmaps[NORMAL].getHeight();
+ }
+
+ protected void layout( int width, int height ) {
+ setExtent( _bitmaps[NORMAL].getWidth(), _bitmaps[NORMAL].getHeight() );
+ }
+
+ protected void paint( Graphics g ) {
+ int index = g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS ) ? FOCUS : NORMAL;
+ g.drawBitmap( 0, 0, _bitmaps[index].getWidth(), _bitmaps[index].getHeight(), _bitmaps[index], 0, 0 );
+ }
+
+ /**
+ * With this commented out the default focus will show through
+ * If an app doesn't want focus colours then it should override this and do nothing
+ **/
+ /*
+ protected void paintBackground( Graphics g ) {
+ // Nothing to do here
+ }
+ */
+
+ protected void drawFocus( Graphics g, boolean on ) {
+ // Paint() handles it all
+ g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, true );
+ paintBackground( g );
+ paint( g );
+ }
+}
+
View
331 Advanced UI/src/com/samples/toolkit/ui/component/BitmapGaugeField.java
@@ -0,0 +1,331 @@
+/*
+* Copyright (c) 2011 Research In Motion Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.samples.toolkit.ui.component;
+
+import net.rim.device.api.system.*;
+import net.rim.device.api.ui.*;
+import net.rim.device.api.util.*;
+
+public class BitmapGaugeField extends Field
+{
+ private Bitmap _imageBackground;
+ private Bitmap _imageProgress;
+
+ private Bitmap _imageCenterBackground;
+ private Bitmap _imageCenterProgress;
+
+ private int _leadingBackgroundClip;
+ private int _trailingBackgroundClip;
+ private int _leadingProgressClip;
+ private int _trailingProgressClip;
+
+ private int _rop;
+
+ private int _numValues;
+ private int _currentValue;
+
+ private boolean _selected;
+ private boolean _horizontal;
+
+ private int _width;
+ private int _height;
+
+ /**
+ * Bitmap status - The image that is used as the state indicator, it grows to fill the field
+ * Bitmap gaugeBackground - the background image is stretched to fit
+ * int numStates - the number of increments. NOTE: this DOES NOT include zero position (will be one larger than you say)
+ * int initialState - NOTE: this INCLUDES ZERO POSITION.
+ *
+ * pre: NumStates must be greater or equal to initialState
+ * pre: NumStates must be greater than 1
+ */
+ public BitmapGaugeField( Bitmap background
+ , Bitmap progress
+ , int numValues
+ , int initialValue
+ , int leadingBackgroundClip
+ , int trailingBackgroundClip
+ , int leadingProgressClip
+ , int trailingProgressClip
+ , boolean horizontal )
+ {
+ super( NON_FOCUSABLE );
+
+ if( numValues < 1 ) {
+ throw( new IllegalArgumentException() );
+ }
+
+ if( leadingBackgroundClip < 0 || trailingBackgroundClip < 0
+ || leadingProgressClip < 0 || trailingProgressClip < 0 ) {
+ throw( new IllegalArgumentException() );
+ }
+
+ _imageBackground = background;
+ _imageProgress = progress;
+
+ _horizontal = horizontal;
+ _numValues = numValues;
+ _currentValue = initialValue;
+
+ _leadingBackgroundClip = leadingBackgroundClip;
+ _trailingBackgroundClip = trailingBackgroundClip;
+ _leadingProgressClip = leadingProgressClip;
+ _trailingProgressClip = trailingProgressClip;
+
+ _rop = _imageBackground.hasAlpha() ? Graphics.ROP_SRC_ALPHA : Graphics.ROP_SRC_COPY;
+
+ setValue( MathUtilities.clamp( 0, initialValue, _numValues ) );
+
+
+ if( _horizontal ) {
+ _imageCenterBackground = new Bitmap( _imageBackground.getWidth() - _leadingBackgroundClip - _trailingBackgroundClip , _imageBackground.getHeight() );
+ } else {
+ _imageCenterBackground = new Bitmap( _imageBackground.getWidth(), _imageBackground.getHeight() - _leadingBackgroundClip - _trailingBackgroundClip );
+ }
+ makeBitmapTransparent( _imageCenterBackground );
+ initTile( _imageBackground, leadingBackgroundClip, trailingBackgroundClip, _imageCenterBackground );
+
+ if( _horizontal ) {
+ _imageCenterProgress = new Bitmap( _imageProgress.getWidth() - _leadingProgressClip - _trailingProgressClip , _imageProgress.getHeight() );
+ } else {
+ _imageCenterProgress = new Bitmap( _imageProgress.getWidth(), _imageProgress.getHeight() - _leadingProgressClip - _trailingProgressClip );
+ }
+ makeBitmapTransparent( _imageCenterProgress );
+ initTile( _imageProgress, leadingProgressClip, trailingProgressClip, _imageCenterProgress );
+ }
+
+ private void makeBitmapTransparent( Bitmap bitmap )
+ {
+ Graphics g = new Graphics( bitmap );
+ g.setGlobalAlpha( 0x00 );
+ g.clear();
+ }
+
+ /**
+ * Change the state of the gauge. Zero is far left.
+ * @param newState - the switch will be set to the specified state
+ */
+ public void setValue(int newValue)
+ {
+ if( newValue > _numValues ){
+ throw new IllegalArgumentException();
+ } else {
+ _currentValue = _horizontal ? newValue : _numValues - newValue;
+ invalidate();
+ }
+ }
+
+ /**
+ * @return The current value that is selected. State zero is on the far left/bottom, and increase to the right/top.
+ */
+ public int getValue()
+ {
+ return _horizontal ? _currentValue : _numValues - _currentValue;
+ }
+
+ /**
+ * @return The number of states the gauge has
+ */
+ public int getNumValues()
+ {
+ return _numValues;
+ }
+
+ public int getPreferredWidth()
+ {
+ return _horizontal ? Display.getWidth() : Math.max( _imageBackground.getWidth(), _imageProgress.getWidth() );
+ }
+
+ public int getPreferredHeight()
+ {
+ return _horizontal ? Math.max( _imageBackground.getHeight(), _imageProgress.getHeight() ) : Display.getHeight();
+ }
+
+ protected void layout( int width, int height )
+ {
+ _width = Math.min( getPreferredWidth(), width );
+ _height = Math.min( getPreferredHeight(), height );
+
+ setExtent( _width, _height );
+ }
+
+ protected boolean navigationMovement(int dx, int dy, int status, int time)
+ {
+ if( _selected ) {
+ if( _horizontal && dx > 0 || !_horizontal && dy < 0) {
+ incrementState();
+ fieldChangeNotify( 0 );
+ return true;
+ } else if( _horizontal && dx < 0 || !_horizontal && dy > 0) {
+ decrementState();
+ fieldChangeNotify( 0 );
+ return true;
+ }
+ }
+ return super.navigationMovement( dx, dy, status, time );
+ }
+
+ public void paint( Graphics g )
+ {
+ if( _horizontal ) {
+ drawHorizontalGauge( g );
+ } else {
+ drawVerticalGauge( g );
+ }
+ }
+
+ private void drawHorizontalGauge( Graphics g )
+ {
+ int progressWidth = (int) ((float) (_width - _leadingProgressClip - _trailingProgressClip) / _numValues * _currentValue) + _leadingProgressClip + _trailingProgressClip;
+
+ drawHorizontalPill( g, _imageBackground, _imageCenterBackground, _leadingBackgroundClip, _trailingBackgroundClip, _width );
+ drawHorizontalPill( g, _imageProgress, _imageCenterProgress, _leadingProgressClip, _trailingProgressClip, progressWidth );
+ }
+
+ private void drawHorizontalPill( Graphics g, Bitmap baseImage, Bitmap centerTile, int clipLeft, int clipRight, int width )
+ {
+ int yPosition = ( _height - baseImage.getHeight() ) >> 1;
+ width = Math.max( width, clipLeft + clipRight );
+
+ // Left
+ g.drawBitmap( 0, yPosition, clipLeft, baseImage.getHeight(), baseImage, 0, 0);
+
+ // Middle
+ g.tileRop( _rop, clipLeft, yPosition, Math.max( 0, width - clipLeft - clipRight ), centerTile.getHeight(), centerTile, 0, 0);
+
+ // Right
+ g.drawBitmap( width - clipRight, yPosition, clipRight, baseImage.getHeight(), baseImage, baseImage.getWidth() - clipRight, 0);
+ }
+
+ private void drawVerticalGauge( Graphics g )
+ {
+ // TODO: The same for the vertical as we did for horizontal
+ }
+
+ protected void paintBackground(Graphics graphics)
+ {
+ // Do nothing
+ }
+
+ protected void drawFocus( Graphics g, boolean on )
+ {
+ boolean oldDrawStyleFocus = g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS );
+ try {
+ if( on ) {
+ g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, true );
+ }
+ paintBackground( g );
+ paint( g );
+ } finally {
+ g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, oldDrawStyleFocus );
+ }
+ }
+
+ public void decrementState()
+ {
+ int currentValue = getValue();
+
+ if( currentValue > 0) {
+ setValue( currentValue - 1 );
+ invalidate();
+ }
+ }
+
+ public void incrementState()
+ {
+ int currentValue = getValue();
+
+ if( currentValue < _numValues ) {
+ setValue( currentValue + 1 );
+ invalidate();
+ }
+ }
+
+
+ /**
+ * Invokes an action on this field. The only action that is recognized by this method is
+ * {@link Field#ACTION_INVOKE}, which toggles this field from being checked and unchecked.
+ */
+ protected boolean invokeAction(int action)
+ {
+ switch(action) {
+ case ACTION_INVOKE: {
+ if( toggleSelected() ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ protected boolean keyChar( char key, int status, int time )
+ {
+ if( key == Characters.SPACE || key == Characters.ENTER ) {
+ if( toggleSelected() ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected boolean trackwheelClick( int status, int time )
+ {
+ if( toggleSelected() ) {
+ return true;
+ }
+ return super.trackwheelClick(status, time);
+ }
+
+ private boolean toggleSelected()
+ {
+ if( isEditable() ) {
+ _selected = !_selected;
+ invalidate();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Cuts up the background image using the specified margins
+ * to create the center portion to be tiled
+ */
+ private void initTile( Bitmap baseImage, int leadingMargin, int trailingMargin, Bitmap targetImage )
+ {
+ int height = baseImage.getHeight();
+ int width = baseImage.getWidth();
+
+ int marginSize = leadingMargin + trailingMargin;
+
+ if( _horizontal ) {
+ copy( baseImage, leadingMargin, 0, width - marginSize, height, targetImage );
+ } else {
+ copy( baseImage, 0, leadingMargin, width, height - marginSize, targetImage );
+ }
+ }
+
+ private void copy(Bitmap src, int x, int y, int width, int height, Bitmap dest)
+ {
+ int[] argbData = new int[width * height];
+ src.getARGB(argbData, 0, width, x, y, width, height);
+ for(int tx = 0; tx < dest.getWidth(); tx += width) {
+ for(int ty = 0; ty < dest.getHeight(); ty += height) {
+ dest.setARGB(argbData, 0, width, tx, ty, width, height);
+ }
+ }
+ }
+}
View
495 Advanced UI/src/com/samples/toolkit/ui/component/BitmapSliderField.java
@@ -0,0 +1,495 @@
+//#preprocessor
+
+/*
+* Copyright (c) 2011 Research In Motion Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.samples.toolkit.ui.component;
+
+import java.lang.Math;
+
+import net.rim.device.api.system.*;
+import net.rim.device.api.ui.*;
+
+
+public class BitmapSliderField extends Field
+{
+ Bitmap _imageThumb;
+
+ Bitmap _imageSlider;
+ Bitmap _imageSliderLeft;
+ Bitmap _imageSliderCenter;
+ Bitmap _imageSliderRight;
+
+ Bitmap _imageSliderFocus;
+ Bitmap _imageSliderFocusLeft;
+ Bitmap _imageSliderFocusCenter;
+ Bitmap _imageSliderFocusRight;
+
+ private int _numStates;
+ private int _currentState;
+ private boolean _selected;
+
+ private int _xLeftBackMargin;
+ private int _xRightBackMargin;
+
+ private int _thumbWidth;
+ private int _thumbHeight;
+
+ private int _totalHeight;
+ private int _totalWidth;
+
+ private int _rop; // for tiling
+
+ private static MenuItem _changeOptionsItem = new ChangeOptionMenuItem();
+
+ private int _backgroundColours[];
+ private int _backgroundSelectedColours[];
+
+ private int _defaultSelectColour = 0x977DED;
+ private int _defaultBackgroundColour = 0xEEEEEE;
+ private int _defaultHoverColour = 0x999999;
+
+ /**
+ * Bitmap thumb - The image that is used as the state indicator, it moves sideways
+ * Bitmap sliderBackground - the background image is stretched to fit, only stretched horizontally
+ * int numStates - the number of increments. NOTE: this DOES NOT include zero position (will be one larger than you say)
+ * int initialState - NOTE: this INCLUDES ZERO POSITION.
+ * int xLeftBackMargin - the amount of the background image to be used as the left side of image
+ * int xRightBackMargin - the amount of background image to be used as right side of image
+ * Everything between the left and right side gets tiled
+ *
+ * pre: NumStates must be greater or equal to initialState
+ * pre: NumStates must be greater than 1
+ */
+ public BitmapSliderField( Bitmap thumb
+ , Bitmap sliderBackground
+ , int numStates
+ , int initialState
+ , int xLeftBackMargin
+ , int xRightBackMargin )
+ {
+ this( thumb, sliderBackground, sliderBackground, numStates, initialState, xLeftBackMargin, xRightBackMargin, FOCUSABLE );
+ }
+
+ public BitmapSliderField( Bitmap thumb
+ , Bitmap sliderBackground
+ , int numStates
+ , int initialState
+ , int xLeftBackMargin
+ , int xRightBackMargin
+ , long style )
+ {
+ this( thumb, sliderBackground, sliderBackground, numStates, initialState, xLeftBackMargin, xRightBackMargin, style );
+ }
+
+ public BitmapSliderField( Bitmap thumb
+ , Bitmap sliderBackground
+ , Bitmap sliderBackgroundFocus
+ , int numStates
+ , int initialState
+ , int xLeftBackMargin
+ , int xRightBackMargin )
+ {
+ this( thumb, sliderBackground, sliderBackgroundFocus, numStates, initialState, xLeftBackMargin, xRightBackMargin, FOCUSABLE );
+ }
+
+ public BitmapSliderField( Bitmap thumb
+ , Bitmap sliderBackground
+ , Bitmap sliderBackgroundFocus
+ , int numStates
+ , int initialState
+ , int xLeftBackMargin
+ , int xRightBackMargin
+ , long style )
+ {
+ super( style );
+
+ if( initialState > numStates || numStates < 2 ){
+ }
+ _imageThumb = thumb;
+ _imageSlider = sliderBackground;
+ _imageSliderFocus = sliderBackgroundFocus;
+ _numStates = numStates;
+ setState( initialState );
+
+ _xLeftBackMargin = xLeftBackMargin;
+ _xRightBackMargin = xRightBackMargin;
+
+ _rop = _imageSlider.hasAlpha() ? Graphics.ROP_SRC_ALPHA : Graphics.ROP_SRC_COPY;
+
+ _thumbWidth = thumb.getWidth();
+ _thumbHeight = thumb.getHeight();
+
+ initBitmaps();
+ }
+
+
+ /**
+ * colours - An array of colours, one for each of the states
+ * selectColours - An array of colours, one for each selected state
+ */
+ public BitmapSliderField( Bitmap thumb
+ , Bitmap sliderBackground
+ , int numStates
+ , int initialState
+ , int xLeftBackMargin
+ , int xRightBackMargin
+ , int[] colours
+ , int[] selectColours )
+ {
+ this(thumb, sliderBackground, sliderBackground, numStates, initialState, xLeftBackMargin, xRightBackMargin, FOCUSABLE );
+
+ if( colours.length != numStates+1 ){
+ throw new IllegalArgumentException();
+ }
+ _backgroundColours = colours;
+ _backgroundSelectedColours = selectColours;
+ }
+
+ /**
+ * Cuts up the background image and margins you provide
+ * to make the left, center, and right bitmaps
+ */
+ public void initBitmaps()
+ {
+ int height = _imageSlider.getHeight();
+
+ _imageSliderLeft = new Bitmap( _xLeftBackMargin, height );
+ _imageSliderCenter = new Bitmap( _imageSlider.getWidth() - _xRightBackMargin - _xLeftBackMargin, height);
+ _imageSliderRight = new Bitmap( _xRightBackMargin, height );
+
+ copy( _imageSlider, 0, 0, _xLeftBackMargin, height, _imageSliderLeft );
+ copy( _imageSlider, _xLeftBackMargin, 0, _imageSlider.getWidth() - _xRightBackMargin - _xLeftBackMargin, height, _imageSliderCenter);
+ copy( _imageSlider, _imageSlider.getWidth() - _xRightBackMargin, 0, _xRightBackMargin, height, _imageSliderRight);
+
+ _imageSliderFocusLeft = new Bitmap( _xLeftBackMargin, height );
+ _imageSliderFocusCenter = new Bitmap( _imageSlider.getWidth() - _xRightBackMargin - _xLeftBackMargin, height);
+ _imageSliderFocusRight = new Bitmap( _xRightBackMargin, height );
+
+ copy( _imageSliderFocus, 0, 0, _xLeftBackMargin, height, _imageSliderFocusLeft );
+ copy( _imageSliderFocus, _xLeftBackMargin, 0, _imageSlider.getWidth() - _xRightBackMargin - _xLeftBackMargin, height, _imageSliderFocusCenter);
+ copy( _imageSliderFocus, _imageSlider.getWidth() - _xRightBackMargin, 0, _xRightBackMargin, height, _imageSliderFocusRight);
+ }
+
+ private void copy(Bitmap src, int x, int y, int width, int height, Bitmap dest) {
+ int[] argbData = new int[width * height];
+ src.getARGB(argbData, 0, width, x, y, width, height);
+ for(int tx = 0; tx < dest.getWidth(); tx += width) {
+ for(int ty = 0; ty < dest.getHeight(); ty += height) {
+ dest.setARGB(argbData, 0, width, tx, ty, width, height);
+ }
+ }
+ }
+
+ /**
+ * Change the state of the switch. Zero is far left
+ * @param on - if true, the switch will be set to on state
+ */
+ public void setState(int newState) {
+ if( newState > _numStates ){
+ throw new IllegalArgumentException();
+ } else {
+ _currentState = newState;
+ invalidate();
+ }
+ }
+
+ /**
+ * @return The current state that is selected
+ * State zero is on the far left, and increase to the right
+ */
+ public int getState() {
+ return _currentState;
+ }
+
+ /**
+ * @return The number of states the slider has
+ */
+ public int getNumStates() {
+ return _numStates;
+ }
+
+ /**
+ * @return The current background colour being used
+ */
+ public int getColour() {
+ if(_backgroundSelectedColours != null) {
+ return _backgroundSelectedColours[getState()];
+ }
+ return 0x000000;
+ }
+
+ public int getPreferredWidth() {
+ return _totalWidth;
+ }
+
+ public int getPreferredHeight() {
+ return _totalHeight;
+ }
+
+ // Similar to TextFields layout()
+ protected void layout( int width, int height ) {
+ if (width < 0 || height < 0)
+ throw new IllegalArgumentException();
+
+ // We'll take all we can get
+ _totalWidth = width;
+
+ // The largest of the two image heights
+ _totalHeight = Math.max(_imageSlider.getHeight(), _imageThumb.getHeight());
+
+ setExtent( _totalWidth, _totalHeight );
+ }
+
+ public void paint( Graphics g )
+ {
+ // Calculate the slider position
+ int sliderHeight = _imageSlider.getHeight();
+ int sliderBackYOffset = ( _totalHeight - sliderHeight ) >> 1;
+
+ // Determine a Background Color for the slider
+ int backgroundColor = _defaultBackgroundColour;
+ if( _backgroundSelectedColours != null || _backgroundColours != null ) {
+
+ if( _selected ) {
+ backgroundColor = _backgroundSelectedColours != null ? _backgroundSelectedColours[getState()] : _defaultSelectColour;
+ } else if(g.isDrawingStyleSet(Graphics.DRAWSTYLE_FOCUS)) {
+ backgroundColor = _backgroundColours != null ? _backgroundColours[getState()] : _defaultHoverColour;
+ } else {
+ backgroundColor = _defaultBackgroundColour;
+ }
+ }
+ g.setColor( backgroundColor );
+ g.fillRect( 1, sliderBackYOffset + 1, _totalWidth - 2, sliderHeight - 2 );
+
+ if(g.isDrawingStyleSet(Graphics.DRAWSTYLE_FOCUS)) {
+ paintSliderBackground( g, _imageSliderFocusLeft, _imageSliderFocusCenter, _imageSliderFocusRight );
+ } else {
+ paintSliderBackground( g, _imageSliderLeft, _imageSliderCenter, _imageSliderRight );
+ }
+
+ // Calculate the thumb position
+ int thumbXOffset = ( ( _totalWidth - _thumbWidth ) * _currentState ) / _numStates;
+
+ // Draw the thumb
+ g.drawBitmap( thumbXOffset, ( _totalHeight - _thumbHeight ) >> 1, _thumbWidth, _thumbHeight, _imageThumb, 0, 0 );
+ }
+
+ private void paintSliderBackground( Graphics g, Bitmap left, Bitmap middle, Bitmap right )
+ {
+ int sliderHeight = _imageSlider.getHeight();
+ int sliderBackYOffset = ( _totalHeight - sliderHeight ) >> 1;
+
+ // Left
+ g.drawBitmap( 0, sliderBackYOffset, _xLeftBackMargin, sliderHeight, left, 0, 0 );//lefttop
+ // Middle
+ g.tileRop( _rop, _xRightBackMargin, sliderBackYOffset, _totalWidth - _xLeftBackMargin - _xRightBackMargin, sliderHeight, middle, 0, 0 );//top
+ // Right
+ g.drawBitmap( _totalWidth - _xRightBackMargin, sliderBackYOffset, _xRightBackMargin, sliderHeight, right, 0, 0 );//lefttop
+ }
+
+ public void paintBackground( Graphics g )
+ {
+ // nothing
+ }
+
+ protected void drawFocus( Graphics g, boolean on )
+ {
+ boolean oldDrawStyleFocus = g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS );
+ try {
+ if( on ) {
+ g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, true );
+ }
+ paint( g );
+ } finally {
+ g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, oldDrawStyleFocus );
+ }
+ }
+
+
+//#ifndef VER_4.6.1 | VER_4.6.0 | VER_4.5.0 | VER_4.2.1 | VER_4.2.0
+ protected boolean touchEvent(TouchEvent message)
+ {
+ boolean isConsumed = false;
+ boolean isOutOfBounds = false;
+ int x = message.getX(1);
+ int y = message.getY(1);
+ // Check to ensure point is within this field
+ if(x < 0 || y < 0 || x > getExtent().width || y > getExtent().height) {
+ isOutOfBounds = true;
+ }
+ switch(message.getEvent()) {
+ case TouchEvent.CLICK:
+ case TouchEvent.MOVE:
+ if( isOutOfBounds ){ return true; }// consume
+ _selected = true; // Pressed effect
+
+ // update state
+ int stateWidth = getExtent().width / _numStates;
+ int numerator = x / stateWidth;
+ int denominator = x % stateWidth;
+ if( denominator > stateWidth / 2 ) {
+ numerator++;
+ }
+ _currentState = numerator;
+ invalidate();
+
+ isConsumed = true;
+ break;
+ case TouchEvent.UNCLICK:
+ if(isOutOfBounds) {
+ _selected = false; // Reset presssed effect
+ return true;
+ }
+
+ // A field change notification is only sent on UNCLICK to allow for recovery
+ // should the user cancel, i.e. click and move off the button
+
+ _selected = false; // Reset pressed effect
+
+ // Update state
+ stateWidth = getExtent().width / _numStates;
+ numerator = x / stateWidth;
+ denominator = x % stateWidth;
+ if( denominator > stateWidth / 2 ) {
+ numerator++;
+ }
+ _currentState = numerator;
+ invalidate();
+
+ fieldChangeNotify(0);
+
+ isConsumed = true;
+ break;
+ }
+ return isConsumed;
+ }
+//#endif
+
+ protected boolean navigationMovement(int dx, int dy, int status, int time)
+ {
+ if( _selected && dx != 0 )
+ {
+ if(dx > 0 || dy > 0) {
+ incrementState();
+ fieldChangeNotify( 0 );
+ return true;
+ } else if(dx < 0 || dy < 0) {
+ decrementState();
+ fieldChangeNotify( 0 );
+ return true;
+ }
+ }
+ return super.navigationMovement( dx, dy, status, time);
+ }
+
+ public void decrementState() {
+ if(_currentState > 0) {
+ _currentState--;
+ invalidate();
+ }
+ }
+
+ public void incrementState() {
+ if(_currentState < _numStates) {
+ _currentState++;
+ invalidate();
+ }
+ }
+
+
+ /**
+ * Invokes an action on this field. The only action that is recognized by this method is
+ * {@link Field#ACTION_INVOKE}, which toggles this field from being checked and unchecked.
+ */
+ protected boolean invokeAction(int action) {
+ switch(action) {
+ case ACTION_INVOKE: {
+ toggleSelected();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Listens for the space key to be pressed
+ * When pressed, state is toggles
+ */
+ protected boolean keyChar( char key, int status, int time ) {
+ if( key == Characters.SPACE || key == Characters.ENTER ) {
+ toggleSelected();
+ return true;
+ }
+
+ return false;
+ }
+
+ protected boolean trackwheelClick( int status, int time ) {
+ if( isEditable() ) {
+ toggleSelected();
+ return true;
+ }
+ return super.trackwheelClick(status, time);
+ }
+
+ /**
+ * Toggles the state of the switch
+ */
+ private void toggleSelected() {
+ _selected = !_selected;
+ invalidate();
+ }
+
+ public void setDirty( boolean dirty )
+ {
+ // We never want to be dirty or muddy
+ }
+
+ public void setMuddy( boolean muddy )
+ {
+ // We never want to be dirty or muddy
+ }
+
+ protected void makeContextMenu(ContextMenu contextMenu) {
+ super.makeContextMenu(contextMenu);
+ if((Ui.getMode() < Ui.MODE_ADVANCED) && isEditable()) {
+ contextMenu.addItem(_changeOptionsItem);
+ }
+ }
+
+ /**
+ * @category Internal InnerClass
+ */
+ static class ChangeOptionMenuItem extends MenuItem {
+ ChangeOptionMenuItem() {
+ super("Select", 30270, 10);
+ }
+
+ ChangeOptionMenuItem(String text) {
+ super(text, 30270, 10);
+ }
+
+ public void run() {
+ BitmapSliderField theSwitch = (BitmapSliderField)getTarget();
+ theSwitch.keyChar(Characters.SPACE, 0, 0); //menu item simulates space
+ }
+
+ public int getPriority() {
+ return 100 + (getTarget().isMuddy() ? 1000 : 0);
+ }
+ };
+}
View
48 Advanced UI/src/com/samples/toolkit/ui/component/ColoredLabelField.java
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2011 Research In Motion Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.samples.toolkit.ui.component;
+
+import net.rim.device.api.ui.Graphics;
+import net.rim.device.api.ui.component.LabelField;
+
+
+public class ColoredLabelField extends LabelField
+{
+ int _foregroundColor;
+ int _foregroundColorFocus;
+
+ public ColoredLabelField( String label, int foregroundColor, long style ) {
+ this( label, foregroundColor,foregroundColor, style );
+ }
+
+ public ColoredLabelField( String label, int foregroundColor, int foregroundColorFocus, long style ) {
+ super( label, style );
+ _foregroundColor = foregroundColor;
+ _foregroundColorFocus = foregroundColorFocus;
+ }
+
+ protected void paint( Graphics g )
+ {
+ int oldColour = g.getColor();
+ try {
+ g.setColor( g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS ) ? _foregroundColorFocus : _foregroundColor );
+ super.paint( g );
+ } finally {
+ g.setColor( oldColour );
+ }
+ }
+}
View
187 Advanced UI/src/com/samples/toolkit/ui/component/EmbossedButtonField.java
@@ -0,0 +1,187 @@
+/*
+* Copyright (c) 2011 Research In Motion Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.samples.toolkit.ui.component;
+
+import net.rim.device.api.system.*;
+import net.rim.device.api.ui.*;
+import net.rim.device.api.util.*;
+
+/**
+ * A custom button field
+ */
+public class EmbossedButtonField extends BaseButtonField
+{
+ public static final long COLOUR_BORDER = 0xc5fd60b0047307a1L; //net.rim.device.api.ui.component.EmbossedButtonField.COLOUR_BORDER
+ public static final long COLOUR_TEXT = 0x16a6e940230dba6bL; //net.rim.device.api.ui.component.EmbossedButtonField.COLOUR_TEXT
+ public static final long COLOUR_TEXT_FOCUS = 0xe208bcf8cb684c98L; //net.rim.device.api.ui.component.EmbossedButtonField.COLOUR_TEXT_FOCUS
+ public static final long COLOUR_BACKGROUND = 0x8d733213d6ac8b3bL; //net.rim.device.api.ui.component.EmbossedButtonField.COLOUR_BACKGROUND
+ public static final long COLOUR_BACKGROUND_FOCUS = 0x3e2cc79e4fd151d3L; //net.rim.device.api.ui.component.EmbossedButtonField.COLOUR_BACKGROUND_FOCUS
+
+ private static final int XPADDING = Display.getWidth() > 320 ? 7 : 5; // TODO: Touchscreen should be different
+ private static final int YPADDING = Display.getWidth() > 320 ? 4 : 3; // TODO: Touchscreen should be different
+ private static final int BEVEL = 2;
+
+ private LongIntHashtable _colourTable;
+ private Font _buttonFont;
+ private String _text;
+ private boolean _pressed;
+
+ private int _width;
+ private int _height;
+
+ public EmbossedButtonField( String text )
+ {
+ this(text, 0);
+ }
+
+ public EmbossedButtonField( String text, long style )
+ {
+ this( text, style, null );
+ }
+
+ public EmbossedButtonField( String text, long style, LongIntHashtable colourTable )
+ {
+ super( Field.FOCUSABLE | style);
+ _text = text;
+ setColourTable( colourTable );
+ }
+
+ public void setColourTable( LongIntHashtable colourTable )
+ {
+ _colourTable = colourTable;
+ invalidate();
+ }
+
+ public int getColour( long colourKey )
+ {
+ if( _colourTable != null ) {
+ int colourValue = _colourTable.get( colourKey );
+ if( colourValue >= 0 ) {
+ return colourValue;
+ }
+ }
+
+ // Otherwise, just use some reasonable default colours
+ if( colourKey == COLOUR_BORDER ) {
+ return 0x212121;
+ } else if( colourKey == COLOUR_TEXT ) {
+ return 0xD6D6D6;
+ } else if( colourKey == COLOUR_TEXT_FOCUS ) {
+ return Color.WHITE;
+ } else if( colourKey == COLOUR_BACKGROUND ) {
+ return isStyle( Field.READONLY ) ? 0x777777 : 0x424242;
+ } else if( colourKey == COLOUR_BACKGROUND_FOCUS ) {
+ return isStyle( Field.READONLY ) ? 0x666688 : 0x185AB5;
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public void setText(String text)
+ {
+ _text = text;
+ }
+
+ public void applyFont()
+ {
+ _buttonFont = getFont().derive(Font.BOLD);
+ }
+
+ public int getPreferredWidth()
+ {
+ return 2 * XPADDING + _buttonFont.getAdvance( _text );
+ }
+
+ protected void onUnfocus()
+ {
+ super.onUnfocus();
+ if( _pressed ) {
+ _pressed = false;
+ invalidate();
+ }
+ }
+
+ protected boolean navigationClick(int status, int time) {
+ _pressed = true;
+ invalidate();
+ return super.navigationClick( status, time );
+ }
+
+ protected boolean navigationUnclick(int status, int time) {
+ _pressed = false;
+ invalidate();
+ return true;
+ }
+
+ public int getPreferredHeight()
+ {
+ return 2 * YPADDING + _buttonFont.getHeight();
+ }
+
+ protected void layout( int width, int height )
+ {
+ setExtent( isStyle( USE_ALL_WIDTH ) ? width : getPreferredWidth(), getPreferredHeight() );
+ _width = getWidth();
+ _height = getHeight();
+ }
+
+ protected void paint( Graphics g )
+ {
+ int oldColour = g.getColor();
+ Font oldFont = g.getFont();
+ try {
+ g.setFont(_buttonFont);
+ g.setColor( g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS ) ? getColour( COLOUR_TEXT_FOCUS ) : getColour( COLOUR_TEXT ) );
+ g.drawText( _text, 0, YPADDING, DrawStyle.HCENTER, _width );
+ } finally {
+ g.setFont( oldFont );
+ g.setColor( oldColour );
+ }
+ }
+
+ protected void paintBackground( Graphics g)
+ {
+ int oldColour = g.getBackgroundColor();
+ int oldAlpha = g.getGlobalAlpha();
+ try {
+ // Border
+ g.setColor( getColour( COLOUR_BORDER ) );
+ g.fillRect( 1, 0, _width - 2, _height );
+ g.fillRect( 0, 1, _width, _height - 2 );
+
+ // Base color
+ g.setColor( g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS ) ? getColour( COLOUR_BACKGROUND_FOCUS ) : getColour( COLOUR_BACKGROUND ) );
+ g.fillRect( 1, 1, _width - 2, _height - 2 );
+
+ // Highlight and lowlight
+ g.setGlobalAlpha( 0x44 );
+ g.setColor( _pressed ? Color.BLACK : Color.WHITE );
+ g.fillRect( 1, 1, _width - 2, BEVEL );
+ g.setColor( _pressed ? Color.WHITE : Color.BLACK );
+ g.fillRect( 0, _height - BEVEL - 1, _width, BEVEL );
+
+ // Base color
+ g.setGlobalAlpha( 0xFF );
+ g.setColor( g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS ) ? getColour( COLOUR_BACKGROUND_FOCUS ) : getColour( COLOUR_BACKGROUND ) );
+ g.fillRect( 2, 2, _width - 4, _height - 4 );
+
+ } finally {
+ g.setBackgroundColor( oldColour );
+ g.setGlobalAlpha( oldAlpha );
+ }
+ }
+}
View
164 Advanced UI/src/com/samples/toolkit/ui/component/HyperlinkButtonField.java
@@ -0,0 +1,164 @@
+/*
+* Copyright (c) 2011 Research In Motion Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.samples.toolkit.ui.component;
+
+import net.rim.device.api.system.*;
+import net.rim.device.api.ui.*;
+import net.rim.device.api.ui.component.LabelField;
+
+
+public class HyperlinkButtonField extends LabelField
+{
+ private int _textColour;
+ private int _textColourFocus;
+ private int _highlightColour;
+
+ private int _menuOrdinal;
+ private int _menuPriority;
+
+ private XYRect _tmpRect = new XYRect();
+
+
+ public HyperlinkButtonField( String text, int textColour, int highlightColour, int menuOrdinal, int menuPriority )
+ {
+ this( text, textColour, textColour, highlightColour, menuOrdinal, menuPriority );
+ }
+
+ public HyperlinkButtonField( String text, int textColour, int textColourFocus, int highlightColour, int menuOrdinal, int menuPriority )
+ {
+ this( text, textColour, textColourFocus, highlightColour, menuOrdinal, menuPriority, 0 );
+ }
+
+
+ public HyperlinkButtonField( String text, int textColour, int textColourFocus, int highlightColour, int menuOrdinal, int menuPriority, long style )
+ {
+ super( text, Field.FOCUSABLE | style );
+
+ _textColour = textColour;
+ _textColourFocus = textColourFocus;
+ _highlightColour = highlightColour;
+ _menuOrdinal = menuOrdinal;
+ _menuPriority = menuPriority;
+ }
+
+ public void applyFont()
+ {
+ Font underlineFont = getFont().derive( Font.UNDERLINED );
+ setFont( underlineFont );
+ }
+
+ protected void paint( Graphics g )
+ {
+ int oldColour = g.getColor();
+ try {
+ if(g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS ) ) {
+ g.setColor( _textColourFocus );
+ } else {
+ g.setColor( _textColour );
+ }
+ super.paint( g );
+ } finally {
+ g.setColor( oldColour );
+ }
+ }
+
+ protected void drawFocus( Graphics g, boolean on )
+ {
+ getFocusRect( _tmpRect );
+
+ boolean oldDrawStyleFocus = g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS );
+ int oldBackgroundColour = g.getBackgroundColor();
+
+ boolean notEmpty = g.pushContext( _tmpRect.x, _tmpRect.y, _tmpRect.width, _tmpRect.height, 0, 0 );
+ try {
+ if( notEmpty ) {
+ if( on ) {
+ g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, true );
+ g.setBackgroundColor( _highlightColour );
+ }
+ g.clear();
+ paint( g );
+ }
+ } finally {
+ g.popContext();
+ g.setBackgroundColor( oldBackgroundColour );
+ g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, oldDrawStyleFocus );
+ }
+ }
+
+
+ protected boolean keyChar( char character, int status, int time )
+ {
+ if( character == Characters.ENTER ) {
+ fieldChangeNotify( 0 );
+ return true;
+ }
+ return super.keyChar( character, status, time );
+ }
+
+ protected boolean trackwheelClick( int status, int time ) {
+ keyChar(Characters.ENTER, status, time );
+ return true;
+ }
+
+ protected boolean invokeAction( int action )
+ {
+ switch( action ) {
+ case ACTION_INVOKE: {
+ fieldChangeNotify( 0 );
+ return true;
+ }
+ }
+ return super.invokeAction( action );
+ }
+
+
+ public void setDirty( boolean dirty )
+ {
+ // We never want to be dirty or muddy
+ }
+
+
+ public void setMuddy( boolean muddy )
+ {
+ // We never want to be dirty or muddy
+ }
+
+
+ public String getMenuText()
+ {
+ return getText();
+ }
+
+
+ /**
+ * Returns a MenuItem that could be used to invoke this link.
+ */
+ public MenuItem getMenuItem()
+ {
+ if( _menuOrdinal < 0
+ || _menuPriority < 0 ) {
+ return null;
+ }
+ return new MenuItem( getMenuText(), _menuOrdinal, _menuPriority ) {
+ public void run() {
+ fieldChangeNotify( 0 );
+ }
+ };
+ }
+
+}
View
243 Advanced UI/src/com/samples/toolkit/ui/component/LabeledSwitch.java
@@ -0,0 +1,243 @@
+/*
+* Copyright (c) 2011 Research In Motion Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.samples.toolkit.ui.component;
+
+import net.rim.device.api.system.*;
+import net.rim.device.api.ui.*;
+
+public class LabeledSwitch extends Field
+{
+ private String _textOn;
+ private String _textOff;
+
+ private int _textWidth;
+ private int _textHeight;
+
+ private int _totalWidth;
+ private int _totalHeight;
+
+ private Bitmap _imageOn;
+ private Bitmap _imageOnFocus;
+ private Bitmap _imageOff;
+ private Bitmap _imageOffFocus;
+
+ private boolean _on;
+ private boolean _selected;
+
+ private Font _labelFont;
+
+ private static MenuItem _changeOptionsItem = new ChangeOptionMenuItem();
+
+ private int _textColour = 0x888888;
+ private int _textColourFocus = 0x000000;
+
+ private int _horizontalTextImageGap;
+
+ private Bitmap _switchImage;
+ private String _labelText;
+
+ public LabeledSwitch( Bitmap imageOn
+ , Bitmap imageOff
+ , Bitmap imageOnFocus
+ , Bitmap imageOffFocus
+ , String textOn
+ , String textOff
+ , boolean onByDefault )
+ {
+ super( Field.FIELD_VCENTER );
+
+ _textOn = textOn;
+ _textOff = textOff;
+
+ _imageOn = imageOn;
+ _imageOff = imageOff;
+ _imageOnFocus = imageOnFocus;
+ _imageOffFocus = imageOffFocus;
+
+ _on = onByDefault;
+ _selected = false;
+
+ _horizontalTextImageGap = _imageOn.getHeight() / 3;
+
+ }
+
+ public void applyFont()
+ {
+ _labelFont = getFont().derive( Font.PLAIN, _imageOn.getHeight() );
+ }
+
+ /**
+ * Change the state of the switch
+ * @param on - if true, the switch will be set to on state
+ */
+ public void setOn(boolean on) {
+ _on = on;
+ invalidate();
+ }
+
+ public boolean getOnState() {
+ return _on;
+ }
+
+ public boolean isFocusable() {
+ return true;
+ }
+
+ public int getPreferredWidth() {
+ return _totalWidth;
+ }
+
+ public int getPreferredHeight() {
+ return _totalHeight;
+ }
+
+ protected void layout( int width, int height ) {
+ //
+ _textWidth = Math.max( _labelFont.getAdvance( _textOn + "a" ), _labelFont.getAdvance( _textOff + "a" ) );
+ _textHeight = _labelFont.getHeight();
+
+ _totalWidth = _imageOn.getWidth() + _horizontalTextImageGap + _textWidth;
+ _totalHeight = _imageOn.getHeight();
+
+ setExtent( _totalWidth, _totalHeight );
+ }
+
+ public void paint( Graphics g )
+ {
+ Font oldFont = g.getFont();
+ int oldColor = g.getColor();
+
+ try {
+
+ if( _on ) {
+ _switchImage = g.isDrawingStyleSet(Graphics.DRAWSTYLE_FOCUS) ? _imageOnFocus : _imageOn;
+ } else {
+ _switchImage = g.isDrawingStyleSet(Graphics.DRAWSTYLE_FOCUS) ? _imageOffFocus : _imageOff;
+ }
+
+ g.setFont( _labelFont );
+
+ // Determine Label Colour
+ g.setColor( g.isDrawingStyleSet(Graphics.DRAWSTYLE_FOCUS) ? _textColourFocus : _textColour );
+
+ // Label
+ g.drawText( _on ? _textOn : _textOff, 0, ( getHeight() - _textHeight ) / 2, DrawStyle.RIGHT, _textWidth );
+
+ // Image
+ g.drawBitmap( _textWidth + _horizontalTextImageGap, 0, _switchImage.getWidth(), _switchImage.getHeight(), _switchImage, 0, 0 );
+
+ } finally {
+ g.setFont( oldFont );
+ g.setColor( oldColor );
+ }
+ }
+
+ public void paintBackground( Graphics g ) {}
+
+ protected void drawFocus( Graphics g, boolean on )
+ {
+ // Paint() handles it all
+ g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, true );
+ paint( g );
+ }
+
+ protected boolean keyChar( char key, int status, int time )
+ {
+ if( key == Characters.SPACE || key == Characters.ENTER ) {
+ toggle();
+ return true;
+ }
+
+ return false;
+ }
+
+ protected boolean navigationClick( int status, int time )
+ {
+ toggle();
+ return true;
+ }
+
+ protected boolean invokeAction( int action )
+ {
+ switch( action ) {
+ case ACTION_INVOKE: {
+ toggle();
+ return true;
+ }
+ }
+ return super.invokeAction( action );
+ }
+
+ protected boolean trackwheelClick( int status, int time )
+ {
+ if( isEditable() ) {
+ toggle();
+ return true;
+ }
+ return super.trackwheelClick(status, time);
+ }
+
+ /**
+ * Toggles the state of the switch
+ */
+ private void toggle()
+ {
+ _on = !_on;
+ invalidate();
+ fieldChangeNotify( 0 );
+ }
+
+ public void setDirty( boolean dirty )
+ {
+ // We never want to be dirty or muddy
+ }
+
+ public void setMuddy( boolean muddy )
+ {
+ // We never want to be dirty or muddy
+ }
+
+ protected void makeContextMenu(ContextMenu contextMenu)
+ {
+ super.makeContextMenu(contextMenu);
+ if((Ui.getMode() < Ui.MODE_ADVANCED) && isEditable()) {
+ contextMenu.addItem(_changeOptionsItem);
+ }
+ }
+
+ /**
+ * @category Internal InnerClass
+ */
+ static class ChangeOptionMenuItem extends MenuItem {
+ ChangeOptionMenuItem() {
+ super("Toggle", 30270, 10);
+ }
+
+ ChangeOptionMenuItem(String text) {
+ super(text, 30270, 10);
+ }
+
+ public void run() {
+ LabeledSwitch theSwitch = (LabeledSwitch)getTarget();
+ theSwitch.toggle();
+ }
+
+ public int getPriority() {
+ return 100 + (getTarget().isMuddy() ? 1000 : 0);
+ }
+ };
+}
View
312 Advanced UI/src/com/samples/toolkit/ui/component/ListStyleButtonField.java
@@ -0,0 +1,312 @@
+//#preprocess
+
+/*
+* Copyright (c) 2011 Research In Motion Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.samples.toolkit.ui.component;
+
+import net.rim.device.api.system.*;
+import net.rim.device.api.ui.*;
+import net.rim.device.api.ui.component.*;
+
+
+public class ListStyleButtonField extends Field
+{
+ public static int DRAWPOSITION_TOP = 0;
+ public static int DRAWPOSITION_BOTTOM = 1;
+ public static int DRAWPOSITION_MIDDLE = 2;
+ public static int DRAWPOSITION_SINGLE = 3;
+
+ private static final int CORNER_RADIUS = 18;
+
+ private static final int HPADDING = Display.getWidth() <= 320 ? 6 : 8;
+ private static final int VPADDING = 4;
+
+ private static final int COLOR_BACKGROUND = 0xFFFFFF;
+ private static final int COLOR_BORDER = 0xBBBBBB;
+ private static final int COLOR_BACKGROUND_FOCUS = 0x186DEF;
+
+
+ private MyLabelField _labelField;
+ private Bitmap _leftIcon;
+ private Bitmap _actionIcon;
+
+ private int _targetHeight;
+ private int _rightOffset;
+ private int _leftOffset;
+ private int _labelHeight;
+
+ private int _drawPosition = -1;
+
+ public ListStyleButtonField( String label, long style )
+ {
+ this( label, null, style );
+ }
+
+ public ListStyleButtonField( String label, Bitmap actionIcon )
+ {
+ this( label, actionIcon, 0 );
+ }
+
+ public ListStyleButtonField( String label, Bitmap actionIcon, long style )
+ {
+ this( null, label, actionIcon, style );
+ }
+
+ public ListStyleButtonField( Bitmap icon, String label, long style )
+ {
+ this( icon, label, null, style );
+ }
+
+ public ListStyleButtonField( Bitmap icon, String label, Bitmap actionIcon, long style )
+ {
+ super( USE_ALL_WIDTH | Field.FOCUSABLE );
+
+ _labelField = new MyLabelField( label, style );
+ _actionIcon = actionIcon;
+ _leftIcon = icon;
+ }
+
+ /**
+ * DRAWPOSITION_TOP | DRAWPOSITION_BOTTOM | DRAWPOSITION_MIDDLE
+ * Determins how the field is drawn (borders)
+ * If none is set, then no borders are drawn
+ */
+ public void setDrawPosition( int drawPosition )
+ {
+ _drawPosition = drawPosition;
+ }
+
+ public String toString()
+ {
+ return _labelField.toString();
+ }
+
+ public void layout( int width, int height )
+ {
+
+ _targetHeight = getFont().getHeight() / 2 * 3 + 2 * VPADDING;
+//#ifndef VER_4.6.1 | VER_4.6.0 | VER_4.5.0 | VER_4.2.1 | VER_4.2.0
+ if( Touchscreen.isSupported() ) {
+ _targetHeight = getFont().getHeight() * 2 + 2 * VPADDING;
+ }
+//#endif
+
+ _leftOffset = HPADDING;
+ if( _leftIcon != null ) {
+ _leftOffset += _leftIcon.getWidth() + HPADDING;
+ }
+
+ _rightOffset = HPADDING;
+ if( _actionIcon != null ) {
+ _rightOffset += _actionIcon.getWidth() + HPADDING;
+ }
+
+ _labelField.layout( width - _leftOffset - _rightOffset, height );
+ _labelHeight = _labelField.getHeight();
+ int labelWidth = _labelField.getWidth();
+
+ if( _labelField.isStyle( DrawStyle.HCENTER ) ) {
+ _leftOffset = ( width - labelWidth ) / 2;
+ } else if ( _labelField.isStyle( DrawStyle.RIGHT ) ) {
+ _leftOffset = width - labelWidth - HPADDING - _rightOffset;
+ }
+
+ int extraVPaddingNeeded = 0;
+ if( _labelHeight < _targetHeight ) {
+ // Make sure that they are at least 1.5 times font height
+ extraVPaddingNeeded = ( _targetHeight - _labelHeight ) / 2;
+ }
+
+ setExtent( width, _labelHeight + 2 * extraVPaddingNeeded );
+ }
+
+ public void setText( String text )
+ {
+ _labelField.setText( text );
+ updateLayout();
+ }
+
+ protected void paint( Graphics g )
+ {
+ // Left Bitmap
+ if( _leftIcon != null ) {
+ g.drawBitmap( HPADDING, VPADDING, _leftIcon.getWidth(), _leftIcon.getHeight(), _leftIcon, 0, 0 );
+ }
+
+ // Text
+ try {
+ g.pushRegion( _leftOffset, ( getHeight() - _labelHeight ) / 2, getWidth() - _leftOffset - _rightOffset, _labelHeight, 0, 0 );
+ _labelField.paint( g );
+ } finally {
+ g.popContext();
+ }
+
+ // Right (Action) Bitmap
+ if( _actionIcon != null ) {
+ g.drawBitmap( getWidth() - HPADDING - _actionIcon.getWidth(), ( getHeight() - _actionIcon.getHeight() ) / 2, _actionIcon.getWidth(), _actionIcon.getHeight(), _actionIcon, 0, 0 );
+ }
+ }
+
+ protected void paintBackground( Graphics g )
+ {
+ if( _drawPosition < 0 ) {
+ // it's like a list field, let the default background be drawn
+ super.paintBackground( g );
+ return;
+ }
+
+ int oldColour = g.getColor();
+
+ int background = g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS ) ? COLOR_BACKGROUND_FOCUS : COLOR_BACKGROUND;
+ try {
+ if( _drawPosition == 0 ) {
+ // Top
+ g.setColor( background );
+ g.fillRoundRect( 0, 0, getWidth(), getHeight() + CORNER_RADIUS, CORNER_RADIUS, CORNER_RADIUS );
+ g.setColor( COLOR_BORDER );
+ g.drawRoundRect( 0, 0, getWidth(), getHeight() + CORNER_RADIUS, CORNER_RADIUS, CORNER_RADIUS );
+ g.drawLine( 0, getHeight() - 1, getWidth(), getHeight() - 1 );
+ } else if( _drawPosition == 1 ) {
+ // Bottom
+ g.setColor( background );
+ g.fillRoundRect( 0, -CORNER_RADIUS, getWidth(), getHeight() + CORNER_RADIUS, CORNER_RADIUS, CORNER_RADIUS );
+ g.setColor( COLOR_BORDER );
+ g.drawRoundRect( 0, -CORNER_RADIUS, getWidth(), getHeight() + CORNER_RADIUS, CORNER_RADIUS, CORNER_RADIUS );
+ } else if( _drawPosition == 2 ) {
+ // Middle
+ g.setColor( background );
+ g.fillRoundRect( 0, -CORNER_RADIUS, getWidth(), getHeight() + 2 * CORNER_RADIUS, CORNER_RADIUS, CORNER_RADIUS );
+ g.setColor( COLOR_BORDER );
+ g.drawRoundRect( 0, -CORNER_RADIUS, getWidth(), getHeight() + 2 * CORNER_RADIUS, CORNER_RADIUS, CORNER_RADIUS );
+ g.drawLine( 0, getHeight() - 1, getWidth(), getHeight() - 1 );
+ } else {
+ // Single
+ g.setColor( background );
+ g.fillRoundRect( 0, 0, getWidth(), getHeight(), CORNER_RADIUS, CORNER_RADIUS );
+ g.setColor( COLOR_BORDER );
+ g.drawRoundRect( 0, 0, getWidth(), getHeight(), CORNER_RADIUS, CORNER_RADIUS );
+ }
+ } finally {
+ g.setColor( oldColour );
+ }
+ }
+
+ protected void drawFocus( Graphics g, boolean on )
+ {
+ if( _drawPosition < 0 ) {
+ super.drawFocus( g, on );
+ } else {
+ boolean oldDrawStyleFocus = g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS );
+ try {
+ if( on ) {
+ g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, true );
+ }
+ paintBackground( g );
+ paint( g );
+ } finally {
+ g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, oldDrawStyleFocus );
+ }
+ }
+ }
+
+ protected boolean keyChar( char character, int status, int time )
+ {
+ if( character == Characters.ENTER ) {
+ clickButton();
+ return true;
+ }
+ return super.keyChar( character, status, time );
+ }
+
+ protected boolean navigationClick( int status, int time )
+ {
+ clickButton();
+ return true;
+ }
+
+ protected boolean trackwheelClick( int status, int time )
+ {
+ clickButton();
+ return true;
+ }
+
+ //#ifndef VER_4.1.0 | 4.0.0
+ protected boolean invokeAction( int action )
+ {
+ switch( action ) {
+ case ACTION_INVOKE: {
+ clickButton();
+ return true;
+ }
+ }
+ return super.invokeAction( action );
+ }
+ //#endif
+
+ /**
+ * A public way to click this button
+ */
+ public void clickButton()
+ {
+ fieldChangeNotify( 0 );
+ }
+
+//#ifndef VER_4.6.1 | VER_4.6.0 | VER_4.5.0 | VER_4.2.1 | VER_4.2.0
+ protected boolean touchEvent( TouchEvent message )
+ {
+ int x = message.getX( 1 );
+ int y = message.getY( 1 );
+ if( x < 0 || y < 0 || x > getExtent().width || y > getExtent().height ) {
+ // Outside the field
+ return false;
+ }
+ switch( message.getEvent() ) {
+
+ case TouchEvent.UNCLICK:
+ clickButton();
+ return true;
+ }
+ return super.touchEvent( message );
+ }
+//#endif
+
+ public void setDirty( boolean dirty ) {}
+ public void setMuddy( boolean muddy ) {}
+
+
+ private static class MyLabelField extends LabelField
+ {
+
+ public MyLabelField( String text, long style )
+ {
+ super( text, style );
+ }
+
+ public void layout( int width, int height )
+ {
+ super.layout( width, height );
+ }
+
+ public void paint( Graphics g )
+ {
+ super.paint( g );
+ }
+ }
+}
+
+
+
View
236 Advanced UI/src/com/samples/toolkit/ui/component/PillButtonField.java
@@ -0,0 +1,236 @@
+/*
+* Copyright (c) 2011 Research In Motion Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+
+package com.samples.toolkit.ui.component;
+
+import com.samples.toolkit.ui.container.PillButtonSet;
+
+import net.rim.device.api.system.*;
+import net.rim.device.api.ui.*;
+
+/**
+ * A custom button field
+ */
+public class PillButtonField extends BaseButtonField
+{
+ private static final int CORNER_RADIUS = 18;
+
+ public static int DRAWPOSITION_LEFT = 0;
+ public static int DRAWPOSITION_RIGHT = 1;
+ public static int DRAWPOSITION_MIDDLE = 2;
+ public static int DRAWPOSITION_SINGLE = 3;
+
+ public static final int COLOUR_BORDER = 0x212121;
+ public static final int COLOUR_BORDER_FOCUS = 0x212121;
+ public static final int COLOUR_BORDER_SELECTED = 0x212121;
+ public static final int COLOUR_TEXT = 0xD6D6D6;
+ public static final int COLOUR_TEXT_FOCUS = 0xFFFFFF;
+ public static final int COLOUR_TEXT_SELECTED = 0xFFFFFF;
+ public static final int COLOUR_BACKGROUND = 0x727272;
+ public static final int COLOUR_BACKGROUND_FOCUS = 0x125DDE;
+ public static final int COLOUR_BACKGROUND_SELECTED = 0x32427E;
+
+ private static final int XPADDING = Display.getWidth() <= 320 ? 6 : 8;
+ private static final int YPADDING = Display.getWidth() <= 320 ? 5 : 7;
+
+ private String _text;
+ private Font _buttonFont;
+ private boolean _pressed = false;
+ private boolean _selected = false;
+
+ private int _width;
+ private int _height;
+
+ private int _drawPosition = -1;
+
+ public PillButtonField( String text )
+ {
+ super( Field.FOCUSABLE );
+ _text = text;
+ }
+
+ /**
+ * DRAWPOSITION_LEFT | DRAWPOSITION_RIGHT | DRAWPOSITION_MIDDLE | DRAWPOSITION_SINGLE
+ * Determins how the field is drawn (border corners)
+ */
+ public void setDrawPosition( int drawPosition )
+ {
+ _drawPosition = drawPosition;
+ }
+
+ public void setSelected( boolean selected )
+ {
+ _selected = selected;
+ invalidate();
+ }
+
+ public int getPreferredWidth()
+ {
+ return 2 * XPADDING + _buttonFont.getAdvance( _text ); // not actually used
+ }
+
+ public int getPreferredHeight()
+ {
+ return 2 * YPADDING + _buttonFont.getHeight();
+ }
+
+ protected void layout( int width, int height )
+ {
+ _buttonFont = getFont();
+ setExtent( width, getPreferredHeight() );
+ _width = getWidth();
+ _height = getHeight();
+ }
+
+ protected void onUnfocus()
+ {
+ super.onUnfocus();
+ if( _pressed ) {
+ _pressed = false;
+ invalidate();
+ }
+ }
+
+ /**
+ * A public way to click this button
+ */
+ public void clickButton()
+ {
+ Manager manager = getManager();
+ if( manager instanceof PillButtonSet ) {
+ ( ( PillButtonSet ) manager ).setSelectedField( this );
+ }
+ super.clickButton();
+ }
+
+ protected boolean navigationClick(int status, int time) {