Adjustable User Interface
Once you start working with UJML and targetting various devices, one thing becomes abundantly clear: Screen sizes are never the same. The screen size may be VGA (640x480), but most likely you won't be able to use the entire screen. What matters to you, the application developer, is not the total screen size, but the "usable screen size". This is the screen area that can be updated by the program.
In order to determine the screen size, UJML provides the API _getIntProperty(). This API takes an integer parameter defined in the DTD file and returns the appropriate information from the system. The two parameters that concern screen size are _PROPERTY_INT_SCREEN_WIDTH and _PROPERTY_INT_SCREEN_HEIGHT. By passing these parameters to _getIntProperty, we can retrieve the width and height of the usable screen area.
This code is boilerplate for the vast majority of applications:
mScrWidth = _getIntProperty( &_PROPERTY_INT_SCREEN_WIDTH; );
mScrHeight = _getIntProperty( &_PROPERTY_INT_SCREEN_HEIGHT; );
From this information, positioning objects on the screen is simply a matter of calculating offsets from the top, bottom, left, and right. If you wish to place an object flush to the right-hand side of the screen, you set its <x> parameter to be mScrWidth - objectwidth. Likewise, placing an object relative to the bottom of the screen means setting its <y> parameter to be the object's height subtracted from mScrHeight.
Knowing this simple concept, it is possible to draw anything, anywhere on the screen (or even off the screen!) However, UJML has some pitfalls which are easily worked around, yet frustrating if you don't realize the problem.
One of the first applications of screen positioning is the use of percentage offsets. Say you want to fill a certain area of the screen with _COLOR_RED. What you may find is that the area you are trying to paint never appears. The problem is a result of UJML's lack of floating point numbers. You can't say "mScrWidth * 0.42" and expect to get 42% of the screen width. UJML only provides integer arithmetic, so in order to get 42% of the screen width, you must first multiply the screen width by 42, then divide it by 100.
mPosX = mScrWidth * 42 / 100; // OK
mPosX = mScrWidth / 100 * 42; // NG: this will lose signficant digits
Keep in mind that integer arithmetic truncates, so don't divide before multiplying!
Another issue that crops up a lot is overlapping percentages. Since integer arithmetic truncates fractional values, sometimes your calculated areas will overlap each other by a pixel. In most cases, this is not a big deal, but for those of us who don't want our applications looking like they were developed by a sysadmin, it makes sense to be aware of this problem.
A decent solution is to use offsets based on the values returned by the percentage calculations. While this may have the side effect of moving the pixel problem off to the edge of the screen, those are pixels that not many people notice anyway. Better to have a row or column of black pixels on the edge of the screen than to have uneven display in the middle.
To implement this, just keep track of where you are positioning items. Then, instead of basing the position of the next item on the x,y origin, base it on the offset from the item immediately adjacent to it.
mPosX = 0; // this is the first object, based on the x,y origin
mPosW = mScrWidth * 42 / 100;
mPosX2 = mPosX + mPosW; // This is the second object, dynamically positioning itself relative to the first object
In a nutshell, that's it. Positioning items on the screen is relatively easy, and UJML provides excellent drawing capabilities for the application developer. Since we can't depend on the screen size of our devices to always be the same, it is important that our applications adapt to the screen size we are given.
In order to determine the screen size, UJML provides the API _getIntProperty(). This API takes an integer parameter defined in the DTD file and returns the appropriate information from the system. The two parameters that concern screen size are _PROPERTY_INT_SCREEN_WIDTH and _PROPERTY_INT_SCREEN_HEIGHT. By passing these parameters to _getIntProperty, we can retrieve the width and height of the usable screen area.
This code is boilerplate for the vast majority of applications:
mScrWidth = _getIntProperty( &_PROPERTY_INT_SCREEN_WIDTH; );
mScrHeight = _getIntProperty( &_PROPERTY_INT_SCREEN_HEIGHT; );
From this information, positioning objects on the screen is simply a matter of calculating offsets from the top, bottom, left, and right. If you wish to place an object flush to the right-hand side of the screen, you set its <x> parameter to be mScrWidth - objectwidth. Likewise, placing an object relative to the bottom of the screen means setting its <y> parameter to be the object's height subtracted from mScrHeight.
Knowing this simple concept, it is possible to draw anything, anywhere on the screen (or even off the screen!) However, UJML has some pitfalls which are easily worked around, yet frustrating if you don't realize the problem.
One of the first applications of screen positioning is the use of percentage offsets. Say you want to fill a certain area of the screen with _COLOR_RED. What you may find is that the area you are trying to paint never appears. The problem is a result of UJML's lack of floating point numbers. You can't say "mScrWidth * 0.42" and expect to get 42% of the screen width. UJML only provides integer arithmetic, so in order to get 42% of the screen width, you must first multiply the screen width by 42, then divide it by 100.
mPosX = mScrWidth * 42 / 100; // OK
mPosX = mScrWidth / 100 * 42; // NG: this will lose signficant digits
Keep in mind that integer arithmetic truncates, so don't divide before multiplying!
Another issue that crops up a lot is overlapping percentages. Since integer arithmetic truncates fractional values, sometimes your calculated areas will overlap each other by a pixel. In most cases, this is not a big deal, but for those of us who don't want our applications looking like they were developed by a sysadmin, it makes sense to be aware of this problem.
A decent solution is to use offsets based on the values returned by the percentage calculations. While this may have the side effect of moving the pixel problem off to the edge of the screen, those are pixels that not many people notice anyway. Better to have a row or column of black pixels on the edge of the screen than to have uneven display in the middle.
To implement this, just keep track of where you are positioning items. Then, instead of basing the position of the next item on the x,y origin, base it on the offset from the item immediately adjacent to it.
mPosX = 0; // this is the first object, based on the x,y origin
mPosW = mScrWidth * 42 / 100;
mPosX2 = mPosX + mPosW; // This is the second object, dynamically positioning itself relative to the first object
In a nutshell, that's it. Positioning items on the screen is relatively easy, and UJML provides excellent drawing capabilities for the application developer. Since we can't depend on the screen size of our devices to always be the same, it is important that our applications adapt to the screen size we are given.
0 Comments:
Post a Comment
<< Home