datafield get position of the datafield on the screen (top half, top quadrant) on watch

so i am working on a datafield, and i need to know where the datafield is on the screen. on the round screen, to be precise. if it's on the bottom left quadrant, the drawing changes entirely. first i thought "hey. i'm going to use obscurity flags", but those don't do what i want. what is the right method?

  • i do use those statements, i just changed the layout file (View.setLayout()), so i can visually see if it has executed. i also have a print statement. it just executes in the mentioned layouts.

    in onLayout()ofcourse

  • Using your if statement, in onLayout() add something like this:

    System.println("check1="+(obscurityflags & OBSCURE_TOP));

    System.println("check2="+ !(obscurityflags & OBSCURE_BOTTOM));

    System.println("check3="+ !(obscurityflags & OBSCURE_LEFT));

    System.println("check4="+ !(obscurityflags & OBSCURE_RIGHT) ):

    To see what's happening with your if statement.

  • the output:

    check1=2
    check2=-9
    check3=-2
    check4=-5

    for the 1 field layout. for the 4 field A layout:

    check1=2
    check2=-1
    check3=-2
    check4=-5

    for the 4 fields B layout:

    check1=2
    check2=-1
    check3=-1
    check4=-5

    3 fields b:

    check1=2
    check2=-1
    check3=-2
    check4=-5

    3 fields a:

    check1=2
    check2=-1
    check3=-2
    check4=-5

    i feel like that's enough examples,

    so know i have this data, i got no idea what i can do with it. tbh i rarely deal with bitwise operators, but i am quite sure that you can only get a 1 or a 0. so i don't understand what tf happend here...

  • Try using something like

    System.println("check1="+((obscurityflags & OBSCURE_TOP)!=0));

    You'll get a boolean instead of a number

  • okay, that !=0 was what i was missing, now i added !=0 to the if statement, and it all works, thanks!

  • so, i celebrated to quickly, cause it will return true, no matter what... any clues?

  • if((obscurityflags & OBSCURE_TOP) && !(obscurityflags & OBSCURE_BOTTOM) && !(obscurityflags & OBSCURE_LEFT))&& !(obscurityflags & OBSCURE_RIGHT) )

    I believe this doesn't work because of a long-standing bug with the ! operator applied to Number/Long returning the bitwise inverse instead of the boolean inverse. This has been on my radar for some time.

    I think you want to write this:

    if( (obscurityflags & OBSCURE_TOP) &&
        ( (obscurityflags & (OBSCURE_BOTTOM | OBSCURE_LEFT | OBSCURE_RIGHT) ) == 0) )
    {
        // obscured on the top but not on left, right or bottom
    }

    If bit-twiddling isn't something you're good at, you can write helper functions...

    function all_of_these_bits_set(field, bits) {
        return (field & bits) == bits;
    }
    
    function any_of_these_bits_set(field, bits) {
        return (field & bits) != 0;
    }
    
    function none_of_these_bits_set(field, bits) {
        return (field & bits) == 0;
    }
    
    function exactly_these_bits_set(field, bits) {
        return field == bits;
    }
    
    if( all_of_these_bits_set(obscurityflags, OBSCURE_TOP) &&
        none_of_these_bits_set(obscurityflags, OBSCURE_BOTTOM | OBSCURE_LEFT | OBSCURE_RIGHT ) )
    {
    
    }

    That said, you can use the obscurity flags to determine which position the field is in a layout, but you can't use that alone to detect which field in which layout is being used. To do that you need both the obscurity and dimensions.

  • The following would detect the data field position and layout for the fenix5:

    var width = dc.getWidth();
    var height = dc.getHeight();
    var obscurity = getObscurityFlags();
    
    if ( height == 240 ) {
        // Field 1 of 1 Field Layout
    }
    else if ( height == 77 )
    
        if( obscurity & OBSCURE_TOP ) {
            // Field 1 of 3 Fields A
            // Field 1 of 4 Fields A
        }
        else {
            // Field 3 of 3 Fields A
            // Field 4 of 4 Fields A
        }
    }
    else if ( height == 82 ) {
    
        if ( obscurity == OBSCURE_LEFT ) {
            // Field 2 of 4 Fields A
        }
        else if ( obscurity == OBSCURE_RIGHT ) {
            // Field 2 of 3 Fields A
        }
        else {
            // Field 3 of 4 Fields A
        }
    }
    else if ( width == 240 ) {
    
        if ( obscurity & OBSCURE_TOP ) {
            // Field 1 of 2 Fields
            // Field 1 of 3 Fields
        }
        else {
            // Field 2 of 2 Fields
        }
    }
    else if ( width == 119 ) {
    
        if ( obscurity & OBSCURE_LEFT )
    
            if ( obscurity & OBSCURE_TOP ) {
                // Field 1 of 4 Fields B
            }
            else {
                // Field 2 of 3 Fields B
                // Field 3 of 4 Fields B
            }
        }
        else {
    
            if ( obscurity & OBSCURE_TOP ) {
                // Field 2 of 4 Fields B
            }
            else {
                // Field 3 of 3 Fields B
                // Field 4 of 4 Fields B
            }
        }
    }
    

    If you are going to support devices with different data field layouts, you should get familiar with build exclusions (either source file exclusions or annotated code exclusions) and jungle files. Typically I'd make a helper function to get the layout resource id for the dimensions/obscurity for device into a single file, then i'd include that file for devices that share the layout.

    // source/MyView.mc
    class MyView extends WatchUi.DataField
    {
        function initialize() {
            DataField.initialize();
        }
        
        function onLayout(dc) {
            var width = dc.getWidth();
            var height = dc.getHeight();
            var obscurity = dc.getObscurityFlags();
            
            // get_field_specific_layout returns a symbol for the layout to load
            var func = new Lang.Method(Rez.Layouts, get_field_specific_layout(width, height, obscurity));
       
            // call that function, just like Rez.Layouts.MyLayout(dc) but MyLayout
            // is the symbol returned from get_field_specific_layout
            setLayout(func.invoke(dc));
        }
    }
    
    // source/fenix5_218x218/Layout.mc
    // 218x218 used by fenix5s, 
    
    function get_field_specific_layout(width, height, obscurity) {
        if (height == 218) {
            return :LayoutField1of1FieldLayout;
        }
        else if ...
    }
    
    // source/fenix5_240x240/Layout.mc
    // 240x240; used by fenix5splus, fenix5plus, fenix5x, fenix5xplus
    
    function get_field_specific_layout(width, height, obscurity) {
        if (height == 240) {
            return :LayoutField1of1FieldLayout;
        }
        else if ...
    }
    
    // source/vivoactive4_218x218/Layout.mc
    // 218x218; used by vivoactive4s, legacyherocaptainmarvel, legacysagarey
    
    function get_field_specific_layout(width, height, obscurity) {
        // ...
    }
    
    // source/vivoactive4_260x260/Layout.mc
    // 260x260; used by vivoactive4, legacyherofirstavenger, legacysagadarthvader
    
    function get_field_specific_layout(width, height, obscurity) {
        // ...
    }
    
    // source/venu_390x390/Layout.mc
    
    function get_field_specific_layout(width, height, obscurity) {
        // ...
    }

    Then add lines to your monkey.jungle file to enable those sources:

    # any device that has the same screen size and layouts as a fenix5s goes here
    # and shares the code for determining the layout
    fenix5s.sourcePath = $(fenix5s.sourcePath);source/fenix5_218x218/*.mc
    
    # any device that has the same screen size and layouts as a fenix5 goes here
    # and shares the code for determining the layout
    fenix5.sourcePath = $(fenix5.sourcePath);source/fenix5_240x240/*.mc
    fenix5x.sourcePath = $(fenix5x.sourcePath);source/fenix5_240x240/*.mc
    fenix5splus.sourcePath = $(fenix5plus.sourcePath);source/fenix5_240x240/*.mc
    fenix5plus.sourcePath = $(fenix5plus.sourcePath);source/fenix5_240x240/*.mc
    fenix5xplus.sourcePath = $(fenix5xplus.sourcePath);source/fenix5_240x240/*.mc
    
    # any device that has the same screen size and layouts as a vivoactive4s goes here
    # and shares the code for determining the layout
    vivoactive4s.sourcePath = $(vivoactive4s.sourcePath);source/vivoactive4_218x218/*.mc
    legacyherocaptianamerica.sourcePath = $(legacyherocaptainamerica.sourcePath);source/vivoactive4_218x218/*.mc
    legacysagarey.sourcePath = $(legacysagarey.sourcePath);source/vivoactive4_218x218/*.mc
    
    ...