mirror of
https://github.com/house-of-abbey/GarminHomeAssistant.git
synced 2025-07-09 22:38:40 +00:00
The newer SDK support tooltips to show the function prototype and help text, so best to make good use of it.
181 lines
6.1 KiB
MonkeyC
181 lines
6.1 KiB
MonkeyC
//-----------------------------------------------------------------------------------
|
|
//
|
|
// 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.
|
|
//
|
|
// J D Abbey & P A Abbey, 28 December 2022
|
|
//
|
|
//-----------------------------------------------------------------------------------
|
|
|
|
using Toybox.Graphics;
|
|
using Toybox.Lang;
|
|
using Toybox.WatchUi;
|
|
using Toybox.Communications;
|
|
using Toybox.Timer;
|
|
|
|
//! ErrorView provides a means to present application errors to the user. These
|
|
//! should not happen of course... but they do, so best make sure errors can be
|
|
//! reported.
|
|
//!
|
|
//! Designed so that a single ErrorView is used for all errors and hence can ensure
|
|
//! that only the first call to display is honoured until the view is dismissed.
|
|
//! This compensates for older devices not being able to call WatchUi.getCurrentView()
|
|
//! due to not supporting API level 3.4.0.
|
|
//!
|
|
//! Usage:
|
|
//! 1) `ErrorView.show("Error message");`
|
|
//! 2) `return ErrorView.create("Error message"); // as Lang.Array<WatchUi.Views or WatchUi.InputDelegates>`
|
|
//
|
|
class ErrorView extends ScalableView {
|
|
private static const scErrorIconMargin as Lang.Float = 7f;
|
|
private var mText as Lang.String = "";
|
|
private var mDelegate as ErrorDelegate;
|
|
// Vertical spacing between the top of the face and the error icon
|
|
private var mErrorIconMargin as Lang.Number;
|
|
private var mErrorIcon;
|
|
private var mTextArea as WatchUi.TextArea or Null;
|
|
private var mAntiAlias as Lang.Boolean = false;
|
|
|
|
private static var instance;
|
|
private static var mShown as Lang.Boolean = false;
|
|
|
|
//! Class Constructor
|
|
//
|
|
function initialize() {
|
|
ScalableView.initialize();
|
|
mDelegate = new ErrorDelegate();
|
|
// Convert the settings from % of screen size to pixels
|
|
mErrorIconMargin = pixelsForScreen(scErrorIconMargin);
|
|
mErrorIcon = Application.loadResource(Rez.Drawables.ErrorIcon) as Graphics.BitmapResource;
|
|
if (Graphics.Dc has :setAntiAlias) {
|
|
mAntiAlias = true;
|
|
}
|
|
}
|
|
|
|
//! Construct the view.
|
|
//!
|
|
//! @param dc Device context
|
|
//
|
|
function onLayout(dc as Graphics.Dc) as Void {
|
|
var w = dc.getWidth();
|
|
|
|
mTextArea = new WatchUi.TextArea({
|
|
:text => mText,
|
|
:color => Graphics.COLOR_WHITE,
|
|
:font => Graphics.FONT_XTINY,
|
|
:justification => Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER,
|
|
:locX => 0,
|
|
:locY => pixelsForScreen(20.0),
|
|
:width => w,
|
|
:height => pixelsForScreen(60.0)
|
|
});
|
|
}
|
|
|
|
//! Update the view
|
|
//!
|
|
//! @param dc Device context
|
|
//
|
|
function onUpdate(dc as Graphics.Dc) as Void {
|
|
var w = dc.getWidth();
|
|
if (mAntiAlias) {
|
|
dc.setAntiAlias(true);
|
|
}
|
|
dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_BLUE);
|
|
dc.clear();
|
|
dc.drawBitmap(w/2 - mErrorIcon.getWidth()/2, mErrorIconMargin, mErrorIcon);
|
|
mTextArea.draw(dc);
|
|
}
|
|
|
|
//! Get this view's delegate for processing events.
|
|
//
|
|
function getDelegate() as ErrorDelegate {
|
|
return mDelegate;
|
|
}
|
|
|
|
//! 'Create' (get) the ErrorView instance, intended to make short work of using this class. E.g.
|
|
//!
|
|
//! `return ErrorView.create("Went wrong!");`
|
|
//!
|
|
//! @param text The string to display in the ErrorView.
|
|
//
|
|
static function create(text as Lang.String) as [ WatchUi.Views ] or [ WatchUi.Views, WatchUi.InputDelegates ] {
|
|
if (instance == null) {
|
|
instance = new ErrorView();
|
|
}
|
|
if (!mShown) {
|
|
instance.setText(text);
|
|
mShown = true;
|
|
}
|
|
return [instance, instance.getDelegate()];
|
|
}
|
|
|
|
//! Create or reuse an existing ErrorView, and pass on the text.
|
|
//!
|
|
//! @param text The string to display in the ErrorView.
|
|
//
|
|
static function show(text as Lang.String) as Void {
|
|
if (!mShown) {
|
|
create(text); // Ignore returned values
|
|
WatchUi.pushView(instance, instance.getDelegate(), WatchUi.SLIDE_UP);
|
|
// This must be last to avoid a race condition with unShow(), where the
|
|
// ErrorView can't be dismissed.
|
|
mShown = true;
|
|
}
|
|
}
|
|
|
|
//! Pop the view and clean up timers.
|
|
//
|
|
static function unShow() as Void {
|
|
if (mShown) {
|
|
WatchUi.popView(WatchUi.SLIDE_DOWN);
|
|
// The call to 'updateMenuItems()' must be on another thread so that the view is popped above.
|
|
var myTimer = new Timer.Timer();
|
|
// Now this feels very "closely coupled" to the application, but it is the most reliable method instead of using a timer.
|
|
myTimer.start(getApp().method(:updateMenuItems), Globals.scApiResume, false);
|
|
// This must be last to avoid a race condition with show(), where the
|
|
// ErrorView can't be dismissed.
|
|
mShown = false;
|
|
}
|
|
}
|
|
|
|
//! Internal show now we're not a static method like 'show()'.
|
|
//!
|
|
//! @param text Change the string tio display in the ErrorView.
|
|
//
|
|
function setText(text as Lang.String) as Void {
|
|
mText = text;
|
|
if (mTextArea != null) {
|
|
mTextArea.setText(text);
|
|
requestUpdate();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//! Delegate for the ErrorView.
|
|
//
|
|
class ErrorDelegate extends WatchUi.BehaviorDelegate {
|
|
|
|
//! Class Constructor
|
|
//!
|
|
function initialize() {
|
|
WatchUi.BehaviorDelegate.initialize();
|
|
}
|
|
|
|
//! Process the event to clear the ErrorView.
|
|
//
|
|
function onBack() as Lang.Boolean {
|
|
getApp().getQuitTimer().reset();
|
|
ErrorView.unShow();
|
|
return true;
|
|
}
|
|
|
|
}
|