Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Developer
Posts: 455
Registered: ‎03-04-2011
My Device: Paper cup

Custom field layout - infinite width

I've got a simple class that's just a colored SeparatorField with variable thickness.  It works when added to a plain MainScreen, but is throwing an IllegalArgumentException due to "Bitmap size too large" when added to a MainScreen with these flags:

 

MainScreen.VERTICAL_SCROLL

MainScreen.HORIZONTAL_SCROLL
MainScreen.VERTICAL_SCROLLBAR

MainScreen.HORIZONTAL_SCROLLBAR

 

There, it works on all real devices, and in most simulators, but is failing for instance in the 4.7 JDE's Storm simulator.  In layout(), the parameters are large numbers, basically infinite.  So it sets that as the extent, which is obviously the problem -- but on the simulators where it works, what the system passes into layout() is the screen width and the line height, so there it seems to be going by getPreferredWidth and getPreferredHeight.

 

What I'm trying to do is have its horizontal size be whatever the size of the parent manager is, so that whether it's part of the screen, the full screen, or horizontal-scrollable beyond the screen, the separator is always a line going all the way across the manager.

 

But it appears that on the Storm simulator, the manager is laying out my field before it's set its own extent.

 

 

package test;


import java.lang.*;
import java.util.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.ui.component.*;


public class ChlinField extends Field {
  public int s, color;
  public ChlinField(int d, int color_p, boolean focusable) {
    super( (focusable) ? Field.FOCUSABLE : Field.NON_FOCUSABLE );
    s = (getFont().getHeight() * d) / 20;
    if (s < 1)
      s = 1;
    color = color_p;
    }
  public int getPreferredWidth() {
    return getManager().getWidth();
    }
  public int getPreferredHeight() {
    return s;
    }
  public void paint(Graphics gx) {
    gx.setBackgroundColor(color);
    gx.clear(gx.getClippingRect());
    }
  public void layout(int w, int h) {
    setExtent(w, (h < s) ? h : s);
    }
  }
  

 

Can someone please clear me up on how this is supposed to work?  I want it to be a general-purpose field, so having it tap into my other code which does know the extent of the scrollable area, is not my first choice -- also, it has to work in things like a PopupScreen where my code does not know the width until after the Manager does, anyway -- so I'm caught with what comes first, the chicken or the egg.

 

Thank you for your help!

Developer
Posts: 2,268
Registered: ‎07-08-2009
My Device: various
My Carrier: various

Re: Custom field layout - infinite width

The Manager always lays out the contained fields before setting its own extent - how could it be otherwise?

One thing to try is to return Integer.MAX_VALUE >> 1 as getPreferredWidth().

 

Anyway - can you tell us what line on code throws that exception?

----------------------------------------------------------
please click 'Accept Solution' on posts that provide the solution to the question you've posted. Don't say "Thanks", press 'Like' button instead!
Developer
Posts: 455
Registered: ‎03-04-2011
My Device: Paper cup

Re: Custom field layout - infinite width

If I use the 9530 sim, then in layout() the width parameter is 360, while the height is still infinite, so the setExtent gets (360, smallnumber) and it's fine.  But in the 9500 sim, layout() parameters are both (effectively) infinity.

 

It always gets through the layout and the setExtent alright, and throws later while preparing to paint:

 

callstack.jpg

 

What's remarkable is that it's working fine on four real devices, and also is on the market downloaded many times with no errors reported.

 

I used the same simulator (4.7 JDE's 9500 sim) during most of the development and testing, with no problem of the sort.  Just after the release I started making another version, and that's when it started throwing, but going back to the original source it's now doing the same thing.  It works in some sims, but not in others.

 

Of course I've got to change how it works "just in case", and for the moment have solved it like this:

 

 

public class ChlinField extends Field { 
  public int s, color;
  protected int w;
  public ChlinField(int d, int color_p, boolean focusable) {
    super( (focusable) ? Field.FOCUSABLE : Field.NON_FOCUSABLE );
    s = (getFont().getHeight() * d) / 20;
    if (s < 1)
      s = 1;
    color = color_p;
    }
  public int getPreferredWidth() {
    return Display.getWidth();
    }
  public int getPreferredHeight() {
    return s;
    }
  public void paint(Graphics gx) {
    gx.setBackgroundColor(color);
    gx.clear(gx.getClippingRect());
    int mw = getManager().getWidth();
    if (mw != w) {
      setExtent(w = mw, s);
      invalidate();
      }
    }
  public void layout(int lw_p, int lh) {
    int pw = getPreferredWidth();
    w = (lw_p < pw) ? lw_p : pw;
    setExtent(w, s);
    }
  }
  

 

 

Wonder how the built-in SeparatorField does it, for example, always size itself as wide as the manager without being a factor in what size the manager becomes?  In this case, if the Manager sizes itself by PreferredWidth, then it would be larger than necessary; I don't want the separator to be a factor in the sizing.

 

Developer
Posts: 723
Registered: ‎03-12-2009
My Device: Playbook

Re: Custom field layout - infinite width

That's one funky looking paint() implementation...
Developer
Posts: 455
Registered: ‎03-04-2011
My Device: Paper cup

Re: Custom field layout - infinite width

Because it doesn't know how wide the manager is until the paint...

 

in the case of my horizontal-scrollable screen, it first sizes to the screen width, and then after the 1st paint resizes to the extended width.  the user doesn't notice it resizing, since it was screen-width to start with, but then when they scroll horizontally, the separator extends the full width of the manager.

 

Is there a better way?   that's what I'm looking for, the correct, clean way to do it.    RIght now, without that resizing in paint(), when they scroll right, the separator is missing toward the right.  So if it were a wide sheet, like a spreadsheet, the lines between rows would be missing except when you're scrolled fully left.

 

 

Developer
Posts: 723
Registered: ‎03-12-2009
My Device: Playbook

Re: Custom field layout - infinite width

[ Edited ]

Why not? The manager should know its dimensions after sublayout is complete, which happens before a paint. The way most of these "infinite" things work is by creating a small "tile" that is at most the dimensions of the screen and drawing it at an offset (scroll x or y) when scrolling. This gives an illusion of "infinite" divider, selection, etc but uses way less memory. i.e. try creating a bitmap with max integer value as width or height, it'll crash.

 

 

Do keep in mind, relayout can be very expensive on BB.  Try your best to only do relayouts only when you absolutely need to.