Counterintuitive terminology?

Am I the only one, or does everybody find the terminology of the WatchUi.PickerFactory and, I would say in many other places in MC, really quite counterintuitive?
For example it seems to me that the function getSize() which we have to code, is described as "Get the number of items in the PickerFactory". But doesn't it actually set the number of items in the PickerFactory?

So shouldn't it be named setSize(), and described as "Set the number of items in the PickerFactory"?
Since so little is explained in the docs, and the examples are frequently obscure and poorly documented, it's taken me 1/2 dat to get to the bottom of this otherwise very useful feature.


  • While I do think there are a few design issues / inconsistencies in Connect IQ / Monkey C, and the documentation can be lacking (to say the least), I don't know if I have a problem with PickerFactory::getSize().

    It def shouldn't be called setSize(), because nobody is calling it to set the size of anything.

    I think here a distinction needs to be made between code in the API that you call, and code that you write for the API to call. Normally the API provides functions for us to call, and in that case, setSize() would make sense.

    In the case of the PickerFactory, it's the opposite: you are writing code which the API will call to create/implement a pickable value. The API wants to know the number of items for that value, so "getSize()" seems appropriate there. (I don't like using the word "value" here, but item was already taken.) Same with getDrawable(): the API is getting the drawable for a given item, based on code that you write; it isn't setting the drawable.

    In some implementations of the Factory Pattern, there might be methods that you can call to set certain attributes after the object is created by the factory. Since some of the attributes for the PickerFactory object can be dynamic (like the drawable), I don't think that would work here.

    I do think PickerFactory should've been called PickerValueFactory, or PickerChooseableFactory, or something, since it doesn't create a Picker, but it creates an object that is used by Pickers to show one or more chooseable values.
  • For example it seems to me that the function getSize() which we have to code, is described as "Get the number of items in the PickerFactory". But doesn't it actually set the number of items in the PickerFactory?


    getSize() and setSize() are public ways of getting and setting the size.

    The public caller of getSize() doesn't really know how it works internally/privately.

    Somebody has to write the internal/private code to implement getSize(). Usually, that somebody isn't you.

    In the PickerFactory situation, you are the person writing the internal/private code.

    [HTML]var items = getSize(); // Public (the caller has no idea what the code is inside the function)

    function getSize() {
    // private
    }
    [/HTML]

    So shouldn't it be named setSize(), and described as "Set the number of items in the PickerFactory"?

    No. The names being used are the standard ones for programming.

  • Ah, the penny is slowly dropping. Thanks, I was missing the distinction that the getSize is not a callback for us to work with, but a function for the API to call, so it is correctly named as we are writing the class that is being called by the API.

    But help me here. The API calls getDrawable to retrieve the displayed item, and passes "index" and "isSelected". "index" I get, as we have to use it to construct the returned drawable, but "isSelected"? I'm running the SDK sample code and it seems that getDrawable is always being called with isSelected true.
  • Maybe it’s to hypothetically allow more than one Picker item to be drawn at the same time — the selected item and a couple of adjacent items. (Like a number spinner on iOS).

    I don’t know if any Garmin Pickers actually implement this (maybe Edge could hypothetically do so, with a larger screen), but it sorta makes sense for the API to specify this possibility today in anticipation of what could be implemented tomorrow. The downside is you might write some unnecessary code today, thus wasting memory.
  • So, hypothetically, how would I code a Picker to cause its PickerFactory to have its getDrawable() called with isSelected as false? Would it be something to do with the way the f/w on the device implements the Picker?
    I suspect it's a place keeper for a future feature.
  • I suspect it's a place keeper for a future feature.


    Yep that’s what I meant. Or it could be a placeholder for a feature that was planned but never implemented.

    You can’t test isSelected = false “properly”. The best you could probably do is hardcode isSelected internally, like in the first line of your getDrawable() or something.

    It’s probably not worth it all to do anything with this. I bet the PickerFactory samples don’t do anything with isSelected.

    I will say that I wish PickerFactory were documented a bit better than “go look at the sample code.” Have to admit that was a bit annoying.
  • You're right, the samples don't do anything with it.
    But you keep teasing me with lines like
    The best you could probably do is hardcode isSelected internally, like in the first line of your getDrawable() or something.
    I really can't see any way to do that (not that I want to!)
  • You can't see what Garmin had in mind for a picker that draws both selected and unselected items, but you can test your code for drawing unselected items just to make sure they look right, assuming you went to trouble of writing it (which I personally wouldn't, especially seeing as the sample code doesn't.)

    function getDrawable(item, selected) {
    // Uncomment the following line to test your code
    // that draws an unselected item
    // selected = false;

    if (selected) {
    // Draw selected item...
    } else {
    // Draw unselected item....
    }
    }


    If you want to get really fancy:

    // Toggle this variable some other place
    // in your code, like through a key sequence or a
    // menu item
    var testUnselectedItem = false;

    function getDrawable(item, selected) {
    selected = !testUnselectedItem;

    if (selected) {
    // Draw selected item...
    } else {
    // Draw unselected item....
    }
    }


    You could even do something crazy like use the value of System.getTimer() and switch between selected and unselected every 5 seconds....

    But yeah, I wouldn't do any of that stuff, personally.