mirror of
				https://github.com/house-of-abbey/GarminHomeAssistant.git
				synced 2025-10-31 07:48:13 +00:00 
			
		
		
		
	Using a Picker to set new value
This commit is contained in:
		| @@ -173,7 +173,7 @@ class HomeAssistantMenuItemFactory { | |||||||
|             } else { |             } else { | ||||||
|                 data.put("entity_id", entity_id); |                 data.put("entity_id", entity_id); | ||||||
|             } |             } | ||||||
|         } |         }  | ||||||
|         var keys = mMenuItemOptions.keys(); |         var keys = mMenuItemOptions.keys(); | ||||||
|         for (var i = 0; i < keys.size(); i++) { |         for (var i = 0; i < keys.size(); i++) { | ||||||
|             options.put(keys[i], mMenuItemOptions.get(keys[i])); |             options.put(keys[i], mMenuItemOptions.get(keys[i])); | ||||||
| @@ -182,7 +182,6 @@ class HomeAssistantMenuItemFactory { | |||||||
|          |          | ||||||
|         return new HomeAssistantNumericMenuItem( |         return new HomeAssistantNumericMenuItem( | ||||||
|             label, |             label, | ||||||
|             entity_id, |  | ||||||
|             template, |             template, | ||||||
|             service, |             service, | ||||||
|             data, |             data, | ||||||
|   | |||||||
| @@ -28,10 +28,7 @@ class HomeAssistantNumericMenuItem extends HomeAssistantMenuItem { | |||||||
|     private var mExit                 as Lang.Boolean; |     private var mExit                 as Lang.Boolean; | ||||||
|     private var mPin                  as Lang.Boolean; |     private var mPin                  as Lang.Boolean; | ||||||
|     private var mData                 as Lang.Dictionary?; |     private var mData                 as Lang.Dictionary?; | ||||||
|     private var mStep                 as Lang.Float=1.0; |     private var mValue                as Lang.String?;   | ||||||
|     private var mValueChanged         as Lang.Boolean = false; |  | ||||||
|     private var mValue                as Lang.Float?;   |  | ||||||
|     private var mEntity               as Lang.String?; |  | ||||||
|     private var mFormatString         as Lang.String="%.1f"; |     private var mFormatString         as Lang.String="%.1f"; | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -51,7 +48,6 @@ class HomeAssistantNumericMenuItem extends HomeAssistantMenuItem { | |||||||
|     // |     // | ||||||
|     function initialize( |     function initialize( | ||||||
|         label     as Lang.String or Lang.Symbol, |         label     as Lang.String or Lang.Symbol, | ||||||
|         entity    as Lang.String, |  | ||||||
|         template  as Lang.String, |         template  as Lang.String, | ||||||
|         service   as Lang.String?, |         service   as Lang.String?, | ||||||
|         data      as Lang.Dictionary?, |         data      as Lang.Dictionary?, | ||||||
| @@ -71,7 +67,6 @@ class HomeAssistantNumericMenuItem extends HomeAssistantMenuItem { | |||||||
|         mPin                  = options[:pin]; |         mPin                  = options[:pin]; | ||||||
|         mLabel                = label; |         mLabel                = label; | ||||||
|         mHomeAssistantService = haService; |         mHomeAssistantService = haService; | ||||||
|         mEntity               = entity; |  | ||||||
|  |  | ||||||
|         HomeAssistantMenuItem.initialize( |         HomeAssistantMenuItem.initialize( | ||||||
|             label, |             label, | ||||||
| @@ -81,22 +76,11 @@ class HomeAssistantNumericMenuItem extends HomeAssistantMenuItem { | |||||||
|                 :icon      => options[:icon] |                 :icon      => options[:icon] | ||||||
|             }  |             }  | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|  |  | ||||||
|        |  | ||||||
|         if  (mData.get("step") != null) { |  | ||||||
|             mStep = mData.get("step").toString().toFloat(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (mData.get("formatString") != null) { |  | ||||||
|             mFormatString=mData.get("formatString").toString(); |  | ||||||
|         } |  | ||||||
|          |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     function callService() as Void { |     function callService() as Void { | ||||||
|         if (!mValueChanged) { return; } |  | ||||||
|         var hasTouchScreen = System.getDeviceSettings().isTouchScreen; |         var hasTouchScreen = System.getDeviceSettings().isTouchScreen; | ||||||
|         if (mPin && hasTouchScreen) { |         if (mPin && hasTouchScreen) { | ||||||
|             var pin = Settings.getPin(); |             var pin = Settings.getPin(); | ||||||
| @@ -145,45 +129,20 @@ class HomeAssistantNumericMenuItem extends HomeAssistantMenuItem { | |||||||
|             onConfirm(false); |             onConfirm(false); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|      |  | ||||||
|  |     | ||||||
|  |  | ||||||
|     //! Callback function after the menu items selection has been (optionally) confirmed. |     //! Callback function after the menu items selection has been (optionally) confirmed. | ||||||
|     //! |     //! | ||||||
|     //! @param b Ignored. It is included in order to match the expected function prototype of the callback method. |     //! @param b Ignored. It is included in order to match the expected function prototype of the callback method. | ||||||
|     // |     // | ||||||
|     function onConfirm(b as Lang.Boolean) as Void { |     function onConfirm(b as Lang.Boolean) as Void { | ||||||
|         if (mService != null) { |         mHomeAssistantService.call(mService, {"entity_id"  => mData.get("entity_id").toString(),mData.get("valueLabel").toString() => mValue}, mExit); | ||||||
|             mHomeAssistantService.call(mService, {"entity_id"  => mEntity,mData.get("valueLabel").toString() => mValue}, mExit); |          | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     ///! Increase value when Up button is pressed or touch screen swipe down  |   | ||||||
|  |  | ||||||
|     function increaseValue() as Void { |  | ||||||
|         if (mValueChanged) |  | ||||||
|         { |  | ||||||
|             mValue += mStep; |  | ||||||
|         } |  | ||||||
|         else { |  | ||||||
|             mValue= getSubLabel().toFloat() + mStep; |  | ||||||
|             mValueChanged=true; |  | ||||||
|         } |  | ||||||
|         setSubLabel(mValue.format(mFormatString)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     ///! Decrease value when Down button is pressed or touch screen swipe up |  | ||||||
|     function decreaseValue() as Void { |  | ||||||
|         if (mValueChanged) |  | ||||||
|         { |  | ||||||
|             mValue -= mStep; |  | ||||||
|         } |  | ||||||
|         else { |  | ||||||
|             mValue= getSubLabel().toFloat() - mStep; |  | ||||||
|             mValueChanged=true; |  | ||||||
|         } |  | ||||||
|         setSubLabel(mValue.format(mFormatString)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     //! Update the menu item's sub label to display the template rendered by Home Assistant. |     //! Update the menu item's sub label to display the template rendered by Home Assistant. | ||||||
|     //! |     //! | ||||||
| @@ -191,12 +150,6 @@ class HomeAssistantNumericMenuItem extends HomeAssistantMenuItem { | |||||||
|     //!             unusually be a number if the SDK interprets the JSON returned by Home Assistant as such. |     //!             unusually be a number if the SDK interprets the JSON returned by Home Assistant as such. | ||||||
|     // |     // | ||||||
|     function updateState(data as Lang.String or Lang.Dictionary or Lang.Number or Lang.Float or Null) as Void { |     function updateState(data as Lang.String or Lang.Dictionary or Lang.Number or Lang.Float or Null) as Void { | ||||||
|         // If vlue has changed, don't use value from HomeAssitant but display target value |  | ||||||
|         if (mValueChanged) { |  | ||||||
|             setSubLabel(mValue.format(mFormatString)); |  | ||||||
|             WatchUi.requestUpdate(); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         if (data == null) { |         if (data == null) { | ||||||
|             setSubLabel($.Rez.Strings.Empty); |             setSubLabel($.Rez.Strings.Empty); | ||||||
|         } else if(data instanceof Lang.String) { |         } else if(data instanceof Lang.String) { | ||||||
| @@ -221,11 +174,16 @@ class HomeAssistantNumericMenuItem extends HomeAssistantMenuItem { | |||||||
|         WatchUi.requestUpdate(); |         WatchUi.requestUpdate(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     //! Set the mValuChanged value. |     //! Set the mValue value. | ||||||
|     //! |     //! | ||||||
|     //! Can be used to reenable update of subLabel |     //! Needed to set new value via the Service call | ||||||
|     // |     // | ||||||
|     function setValueChanged(b as Lang.Boolean) as Void { |     function setValue(value as Lang.String) as Void { | ||||||
|         mValueChanged = b; |         mValue = value; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     function getData() as Lang.Dictionary { | ||||||
|  |         return mData; | ||||||
|  |     } | ||||||
|  |      | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,212 +0,0 @@ | |||||||
| //----------------------------------------------------------------------------------- |  | ||||||
| // |  | ||||||
| // Distributed under MIT Licence |  | ||||||
| //   See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE. |  | ||||||
| // |  | ||||||
| //----------------------------------------------------------------------------------- |  | ||||||
| // |  | ||||||
| // GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely |  | ||||||
| // tested on a Venu 2 device. The source code is provided at: |  | ||||||
| //            https://github.com/house-of-abbey/GarminHomeAssistant. |  | ||||||
| // |  | ||||||
| // P A Abbey & J D Abbey & Someone0nEarth & moesterheld, 31 October 2023 |  | ||||||
| // |  | ||||||
| //----------------------------------------------------------------------------------- |  | ||||||
|  |  | ||||||
| using Toybox.Application; |  | ||||||
| using Toybox.Lang; |  | ||||||
| using Toybox.Graphics; |  | ||||||
| using Toybox.System; |  | ||||||
| using Toybox.WatchUi; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| using Toybox.Application.Properties; |  | ||||||
| using Toybox.Timer; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //! Home Assistant menu construction. |  | ||||||
| // |  | ||||||
| class HomeAssistantNumericView extends WatchUi.Menu2 { |  | ||||||
|  |  | ||||||
|     private var mMenuItem as HomeAssistantNumericMenuItem; |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     //! Class Constructor |  | ||||||
|     // |  | ||||||
|     function initialize( |  | ||||||
|        menuItem as HomeAssistantNumericMenuItem |  | ||||||
|  |  | ||||||
|     ) { |  | ||||||
|         mMenuItem = menuItem;         |  | ||||||
|  |  | ||||||
|         WatchUi.Menu2.initialize({:title => mMenuItem.getLabel()}); |  | ||||||
|          |  | ||||||
|         addItem(mMenuItem); |  | ||||||
|  |  | ||||||
|         //updateState(mData); |  | ||||||
|          |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|     //! Return the menu item |  | ||||||
|     //! |  | ||||||
|     //! @return A HomeAssitantTapMenuItem (or null). |  | ||||||
|     // |  | ||||||
|     function getMenuItem() as HomeAssistantNumericMenuItem? { |  | ||||||
|         return mMenuItem; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     //! Update the menu item's sub label to display the template rendered by Home Assistant. |  | ||||||
|     //! |  | ||||||
|     //! @param data The rendered template (typically a string) to be placed in the sub label. This may |  | ||||||
|     //!             unusually be a number if the SDK interprets the JSON returned by Home Assistant as such. |  | ||||||
|     // |  | ||||||
|     function updateState(data as Lang.String or Lang.Dictionary or Lang.Number or Lang.Float or Null) as Void { |  | ||||||
|         if (data == null) { |  | ||||||
|             mMenuItem.setSubLabel($.Rez.Strings.Empty); |  | ||||||
|         } else if(data instanceof Lang.String) { |  | ||||||
|             mMenuItem.setSubLabel(data); |  | ||||||
|         } else if(data instanceof Lang.Number) { |  | ||||||
|             var d = data as Lang.Number; |  | ||||||
|             mMenuItem.setSubLabel(d.format("%d")); |  | ||||||
|         } else if(data instanceof Lang.Float) { |  | ||||||
|             var f = data as Lang.Float; |  | ||||||
|             mMenuItem.setSubLabel(f.format("%f")); |  | ||||||
|         } else if(data instanceof Lang.Dictionary) { |  | ||||||
|             // System.println("HomeAssistantMenuItem updateState() data = " + data); |  | ||||||
|             if (data.get("error") != null) { |  | ||||||
|                 mMenuItem.setSubLabel($.Rez.Strings.TemplateError); |  | ||||||
|             } else { |  | ||||||
|                 mMenuItem.setSubLabel($.Rez.Strings.PotentialError); |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             // The template must return a Lang.String, Number or Float, or the item cannot be formatted locally without error. |  | ||||||
|             mMenuItem.setSubLabel(WatchUi.loadResource($.Rez.Strings.TemplateError) as Lang.String); |  | ||||||
|         } |  | ||||||
|         WatchUi.requestUpdate(); |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|  |  | ||||||
|     //! Return a list of items that need to be updated within this menu structure. |  | ||||||
|     //! |  | ||||||
|     //! MN. Lang.Array.addAll() fails structural type checking without including "Null" in the return type |  | ||||||
|     //! |  | ||||||
|     //! @return An array of menu items that need to be updated periodically to reflect the latest Home Assistant state. |  | ||||||
|     // |  | ||||||
|     function getItemsToUpdate() as Lang.Array<HomeAssistantToggleMenuItem or HomeAssistantTapMenuItem or HomeAssistantGroupMenuItem or Null> { |  | ||||||
|         var fullList = []; |  | ||||||
|         var lmi = mItems as Lang.Array<WatchUi.MenuItem>; |  | ||||||
|  |  | ||||||
|         for(var i = 0; i < mItems.size(); i++) { |  | ||||||
|             var item = lmi[i]; |  | ||||||
|             if (item instanceof HomeAssistantGroupMenuItem) { |  | ||||||
|                 // Group menu items can now have an optional template to evaluate |  | ||||||
|                 var gmi = item as HomeAssistantGroupMenuItem; |  | ||||||
|                 if (gmi.hasTemplate()) { |  | ||||||
|                     fullList.add(item); |  | ||||||
|                 } |  | ||||||
|                 fullList.addAll(item.getMenuView().getItemsToUpdate()); |  | ||||||
|             } else if (item instanceof HomeAssistantToggleMenuItem) { |  | ||||||
|                 fullList.add(item); |  | ||||||
|             } else if (item instanceof HomeAssistantTapMenuItem) { |  | ||||||
|                 var tmi = item as HomeAssistantTapMenuItem; |  | ||||||
|                 if (tmi.hasTemplate()) { |  | ||||||
|                     fullList.add(item); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         return fullList; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     //! Called when this View is brought to the foreground. Restore |  | ||||||
|     //! the state of this View and prepare it to be shown. This includes |  | ||||||
|     //! loading resources into memory. |  | ||||||
|     function onShow() as Void {} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //! Delegate for the HomeAssistantView. |  | ||||||
| //! |  | ||||||
| //! Reference: https://developer.garmin.com/connect-iq/core-topics/input-handling/ |  | ||||||
| // |  | ||||||
| class HomeAssistantNumericViewDelegate extends WatchUi.Menu2InputDelegate { |  | ||||||
|     private var mIsRootMenuView as Lang.Boolean = false; |  | ||||||
|     private var mTimer          as QuitTimer; |  | ||||||
|     private var mItem           as HomeAssistantNumericMenuItem; |  | ||||||
|  |  | ||||||
|     //! Class Constructor |  | ||||||
|     //! |  | ||||||
|     //! @param isRootMenuView As menus can be nested, this state marks the top level menu so that the |  | ||||||
|     //!                       back event can exit the application completely rather than just popping |  | ||||||
|     //!                       a menu view. |  | ||||||
|     //tap |  | ||||||
|     function initialize(isRootMenuView as Lang.Boolean, item as HomeAssistantNumericMenuItem) { |  | ||||||
|         Menu2InputDelegate.initialize(); |  | ||||||
|         mIsRootMenuView = isRootMenuView; |  | ||||||
|         mTimer          = getApp().getQuitTimer(); |  | ||||||
|         mItem           = item; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     //! Handle the back button (ESC) |  | ||||||
|     // |  | ||||||
|     function onBack() { |  | ||||||
|         mTimer.reset(); |  | ||||||
|  |  | ||||||
|         mItem.setValueChanged(false); |  | ||||||
|  |  | ||||||
|         if (mIsRootMenuView) { |  | ||||||
|             // If its started from glance or as an activity, directly exit the widget/app |  | ||||||
|             // (on widgets without glance, this exit() won't do anything, |  | ||||||
|             // so the base view will be shown instead, through the popView below this "if body") |  | ||||||
|             System.exit(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         WatchUi.popView(WatchUi.SLIDE_RIGHT); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     //! Only for CheckboxMenu |  | ||||||
|     // |  | ||||||
|     function onDone() { |  | ||||||
|         mTimer.reset(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     //! Only for CustomMenu |  | ||||||
|     // |  | ||||||
|     function onFooter() { |  | ||||||
|         mTimer.reset(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Decrease Value |  | ||||||
|     function onNextPage() as Lang.Boolean { |  | ||||||
|         mItem.decreaseValue(); |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
|     //Increase Value |  | ||||||
|     function onPreviousPage() as Lang.Boolean { |  | ||||||
|         mItem.increaseValue(); |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     |  | ||||||
|     //! Select event |  | ||||||
|     //! |  | ||||||
|     //! @param item Selected menu item. |  | ||||||
|     // |  | ||||||
|     function onSelect(item as WatchUi.MenuItem) as Void { |  | ||||||
|         mTimer.reset(); |  | ||||||
|         mItem.callService(); |  | ||||||
|         WatchUi.popView(WatchUi.SLIDE_RIGHT); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     //! Only for CustomMenu |  | ||||||
|     // |  | ||||||
|     function onTitle() { |  | ||||||
|         mTimer.reset(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -271,12 +271,18 @@ class HomeAssistantViewDelegate extends WatchUi.Menu2InputDelegate { | |||||||
|         } else if (item instanceof HomeAssistantNumericMenuItem) { |         } else if (item instanceof HomeAssistantNumericMenuItem) { | ||||||
|             var haItem = item as HomeAssistantNumericMenuItem; |             var haItem = item as HomeAssistantNumericMenuItem; | ||||||
|             // System.println(haItem.getLabel() + " " + haItem.getId()); |             // System.println(haItem.getLabel() + " " + haItem.getId()); | ||||||
|             // create new view to select new valu |             // create new view to select new value | ||||||
|             var numView = new HomeAssistantNumericView(haItem); |             | ||||||
|             WatchUi.pushView(numView, new HomeAssistantNumericViewDelegate(false,haItem), WatchUi.SLIDE_LEFT); |             var mPickerFactory = new HomeAssistantNumericFactory(haItem.getData()); | ||||||
|  |             | ||||||
|  |             var mPicker = new HomeAssistantNumericPicker(mPickerFactory,haItem);//{:pattern => [mPickerFactory}); | ||||||
|  |             var mPickerDelegate = new HomeAssistantNumericPickerDelegate(mPicker); | ||||||
|  |             WatchUi.pushView(mPicker,mPickerDelegate,WatchUi.SLIDE_LEFT); | ||||||
|  |             //WatchUi.pushView(numView, new HomeAssistantNumericViewDelegate(false,haItem), WatchUi.SLIDE_LEFT); | ||||||
|         } else if (item instanceof HomeAssistantGroupMenuItem) { |         } else if (item instanceof HomeAssistantGroupMenuItem) { | ||||||
|             var haMenuItem = item as HomeAssistantGroupMenuItem; |             var haMenuItem = item as HomeAssistantGroupMenuItem; | ||||||
|             // System.println("IconMenu: " + haMenuItem.getLabel() + " " + haMenuItem.getId()); |             // System.println("IconMenu: " + haMenuItem.getLabel() + " " + haMenuItem.getId()); | ||||||
|  |  | ||||||
|             WatchUi.pushView(haMenuItem.getMenuView(), new HomeAssistantViewDelegate(false), WatchUi.SLIDE_LEFT); |             WatchUi.pushView(haMenuItem.getMenuView(), new HomeAssistantViewDelegate(false), WatchUi.SLIDE_LEFT); | ||||||
|         // } else { |         // } else { | ||||||
|         //     System.println(item.getLabel() + " " + item.getId()); |         //     System.println(item.getLabel() + " " + item.getId()); | ||||||
|   | |||||||
							
								
								
									
										88
									
								
								source/factory/HomeAssistantNumericFactory.mc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								source/factory/HomeAssistantNumericFactory.mc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | |||||||
|  | //----------------------------------------------------------------------------------- | ||||||
|  | // | ||||||
|  | // Distributed under MIT Licence | ||||||
|  | //   See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE. | ||||||
|  | // | ||||||
|  | //----------------------------------------------------------------------------------- | ||||||
|  | // | ||||||
|  | // GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely | ||||||
|  | // tested on a Venu 2 device. The source code is provided at: | ||||||
|  | //            https://github.com/house-of-abbey/GarminHomeAssistant. | ||||||
|  | // | ||||||
|  | // P A Abbey & J D Abbey & Someone0nEarth, 31 October 2023 | ||||||
|  | // | ||||||
|  | //------------------------------------------------------------ | ||||||
|  |  | ||||||
|  | import Toybox.Graphics; | ||||||
|  | import Toybox.Lang; | ||||||
|  | import Toybox.WatchUi; | ||||||
|  |  | ||||||
|  | //! Factory that controls which numbers can be picked | ||||||
|  | class HomeAssistantNumericFactory extends WatchUi.PickerFactory { | ||||||
|  |     // define default values in case not contained in data | ||||||
|  |     private var mStart as Lang.Float = 0.0; | ||||||
|  |     private var mStop as Lang.Float = 100.0; | ||||||
|  |     private var mStep as Lang.Float = 1.0; | ||||||
|  |     private var mFormatString as Lang.String = "%.2f"; | ||||||
|  |  | ||||||
|  |     //! Class Constructor | ||||||
|  |     //! | ||||||
|  |     public function initialize(data as Lang.Dictionary) { | ||||||
|  |         PickerFactory.initialize(); | ||||||
|  |  | ||||||
|  |         // Get values from data | ||||||
|  |  | ||||||
|  |         var val = data.get("start"); | ||||||
|  |         if (val != null) { | ||||||
|  |             mStart = val.toString().toFloat(); | ||||||
|  |         } | ||||||
|  |         val = data.get("stop"); | ||||||
|  |         if (val != null) { | ||||||
|  |             mStop = val.toString().toFloat(); | ||||||
|  |         }  | ||||||
|  |         val = data.get("step"); | ||||||
|  |         if (val != null) { | ||||||
|  |             mStep = val.toString().toFloat(); | ||||||
|  |         }  | ||||||
|  |        val = data.get("formatString"); | ||||||
|  |         if (val != null) { | ||||||
|  |             mFormatString = val.toString(); | ||||||
|  |         }  | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //! Get the index of a number item | ||||||
|  |     //! @param value The number to get the index of | ||||||
|  |     //! @return The index of the number | ||||||
|  |     public function getIndex(value as Float) as Number { | ||||||
|  |         return ((value / mStep) - mStart).toNumber(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //! Generate a Drawable instance for an item | ||||||
|  |     //! @param index The item index | ||||||
|  |     //! @param selected true if the current item is selected, false otherwise | ||||||
|  |     //! @return Drawable for the item | ||||||
|  |     public function getDrawable(index as Number, selected as Boolean) as Drawable? { | ||||||
|  |         var value = getValue(index); | ||||||
|  |         var text = "No item"; | ||||||
|  |         if (value instanceof Float) { | ||||||
|  |             text = value.format(mFormatString); | ||||||
|  |         } | ||||||
|  |         return new WatchUi.Text({:text=>text, :color=>Graphics.COLOR_WHITE,  | ||||||
|  |             :locX=>WatchUi.LAYOUT_HALIGN_CENTER, :locY=>WatchUi.LAYOUT_VALIGN_CENTER}); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //! Get the value of the item at the given index | ||||||
|  |     //! @param index Index of the item to get the value of | ||||||
|  |     //! @return Value of the item | ||||||
|  |     public function getValue(index as Number) as Object? { | ||||||
|  |         return mStart + (index * mStep); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //! Get the number of picker items | ||||||
|  |     //! @return Number of items | ||||||
|  |     public function getSize() as Number { | ||||||
|  |         return ((mStop - mStart) / mStep).toNumber() + 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										102
									
								
								source/picker/HomeAssistantNumericPicker.mc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								source/picker/HomeAssistantNumericPicker.mc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | |||||||
|  | //----------------------------------------------------------------------------------- | ||||||
|  | // | ||||||
|  | // Distributed under MIT Licence | ||||||
|  | //   See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE. | ||||||
|  | // | ||||||
|  | //----------------------------------------------------------------------------------- | ||||||
|  | // | ||||||
|  | // GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely | ||||||
|  | // tested on a Venu 2 device. The source code is provided at: | ||||||
|  | //            https://github.com/house-of-abbey/GarminHomeAssistant. | ||||||
|  | // | ||||||
|  | // P A Abbey & J D Abbey & Someone0nEarth, 31 October 2023 | ||||||
|  | // | ||||||
|  | //------------------------------------------------------------ | ||||||
|  |  | ||||||
|  | using Toybox.Application; | ||||||
|  | using Toybox.Lang; | ||||||
|  | using Toybox.Graphics; | ||||||
|  | using Toybox.System; | ||||||
|  | using Toybox.WatchUi; | ||||||
|  |  | ||||||
|  | //! Picker that allows the user to choose a float value | ||||||
|  | class HomeAssistantNumericPicker extends WatchUi.Picker { | ||||||
|  |  | ||||||
|  |     private var mFactory as HomeAssistantNumericFactory; | ||||||
|  |     private var mItem as HomeAssistantNumericMenuItem; | ||||||
|  |  | ||||||
|  |     //! Constructor | ||||||
|  |     public function initialize(factory as HomeAssistantNumericFactory, haItem as HomeAssistantNumericMenuItem) { | ||||||
|  |  | ||||||
|  |         mFactory = factory; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         var pickerOptions = {:pattern=>[mFactory]}; | ||||||
|  |         mItem=haItem; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         var data = mItem.getData(); | ||||||
|  |  | ||||||
|  |         var start = 0.0; | ||||||
|  |         var val = data.get("start"); | ||||||
|  |         if (val != null) { | ||||||
|  |             start = val.toString().toFloat(); | ||||||
|  |         }  | ||||||
|  |         var step = 1.0; | ||||||
|  |         val = data.get("step"); | ||||||
|  |         if (val != null) { | ||||||
|  |             step = val.toString().toFloat(); | ||||||
|  |         }  | ||||||
|  |         val = haItem.getSubLabel().toFloat(); | ||||||
|  |         var index = ((val -start) / step).toNumber(); | ||||||
|  |  | ||||||
|  |         pickerOptions[:defaults]  =[index]; | ||||||
|  |  | ||||||
|  |         var title = new WatchUi.Text({:text=>haItem.getLabel(), :locX=>WatchUi.LAYOUT_HALIGN_CENTER, | ||||||
|  |                 :locY=>WatchUi.LAYOUT_VALIGN_BOTTOM}); | ||||||
|  |         pickerOptions[:title] = title; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         Picker.initialize(pickerOptions); | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     //! Get whether the user is done picking | ||||||
|  |     //! @param value Value user selected | ||||||
|  |     //! @return true if user is done, false otherwise | ||||||
|  |     public function onConfirm(value as Lang.String) as Void { | ||||||
|  |         mItem.setValue(value); | ||||||
|  |         mItem.callService(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |      | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //! Responds to a numeric  picker selection or cancellation | ||||||
|  | class HomeAssistantNumericPickerDelegate extends WatchUi.PickerDelegate { | ||||||
|  |     private var mPicker as HomeAssistantNumericPicker; | ||||||
|  |  | ||||||
|  |     //! Constructor | ||||||
|  |     public function initialize(picker as HomeAssistantNumericPicker) { | ||||||
|  |         PickerDelegate.initialize(); | ||||||
|  |         mPicker = picker; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //! Handle a cancel event from the picker | ||||||
|  |     //! @return true if handled, false otherwise | ||||||
|  |     public function onCancel() as Lang.Boolean { | ||||||
|  |         WatchUi.popView(WatchUi.SLIDE_RIGHT); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //! Handle a confirm event from the picker | ||||||
|  |     //! @param values The values chosen in the picker | ||||||
|  |     //! @return true if handled, false otherwise | ||||||
|  |     public function onAccept(values as Lang.Array) as Lang.Boolean { | ||||||
|  |         var chosenValue = values[0].toString(); | ||||||
|  |         mPicker.onConfirm(chosenValue); | ||||||
|  |         WatchUi.popView(WatchUi.SLIDE_RIGHT); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user