scaling swt on high-resolution screens
DESCRIPTION
In the past couple of years the monitor pixel resolution has increased dramatically. Some years ago we were all happy with HD resolution or even Full HD resolution. Then "Retina" displays were promoted and now we reached a new all time height with 4 K monitors. Monitors with 4000 pixel in width. So how do we write SWT code that runs on 800 x 600 AND also on 3840 x 2160 ? While there are good strategies for scaling applications on Smartphones (iPhones and Android phones each using different approaches) there is no single good approach for desktops. As an example think of a Login Dialog that you set to a fixed size of 400 x 200 pixels. Thats work great on a lot of screens but then the resolution goes up and the physical size stays the same and soon you need a magnifying glass to read it. Or Icons that you supplied with 16x16 pixels. Leaving them small or upscaling them is not an option. So what is the solution here ? This presentation will concentrate on desktop applications and covers all of the following aspects - Examples of well-known applications that fail when asked to scale up to high resolution - Which parts of SWT scales automatically and where do you need to add your own logic ? - Frame and Dialog - Layouts - Layouts used for SWT views - Layouts used for tables (header, column formatter) - Images - icons in buttons, menuitems, toolbars - icon in various sizes - icons using SVG - Scaling the whole application - navigation area - close application button - title bars Most the proposed approaches are also available in Eclipse Riena (which we use as guinea pig) but can be achieved with any SWT application.TRANSCRIPT
Scaling SWT on high-res screens
Christian Campo, ECE 2014
• High resolution Displays • „Windows“ based Scaling • Desktop Applications based Scaling
› Layout (Size, Gap) › Icons › SVG
• Use Eclipse Riena as an example
Overview
Growing Resolutions
3840 x 2160 * taken from Wikipedia
Growing Displaysizes
* taken from Commons Wikimedia
30 2560 x 1600
Example Displaysizes 24 1920 x 1080
27 2560 x 1440
13 2560 x 1600
Resolution vs Size
Riena Example 1300 x 800
30 2560 x 1600
24 1920 x 1080
Riena Example
13 2560 x 1600
Resolution
› 3840*2160
• Smartphones › Scaling Up is very common › Same UI on different resolution / sizes
• „Windows“ › no automatic scaling › Ability for the user to define a scaling
Scaling Up
• „Make text and other items larger or smaller“ • Applied after Logoff and Login • Change of „Logical DPI“ not „Physical DPI“ • 100 % = 96 DPI
Scaling Up in „Windows“
Eclipse IDE - Resolution
› 3840*2160– Skalierung 100 %
Eclipse IDE - Resolution
› 3840*2160 – Skalierung 150 % (Standard)
Eclipse IDE - Resolution
› 3840*2160 – Skalierung 200 %
• Doesnt work well with all applications • Problems
› Widgets or text are not scaled › Blury Icons, Images › Icons are upscaled
Scaling Up in „Windows“
VLC
100 % 150 %
• Buttons DONT scale • Text scales
GLIPS
100 % 150 %
- Menu blurry (Icon, Text)
Adobe Reader
Notepad
500 %
Too small Gap Menu
Control Panel -> Display
500 %
• Change „DPI“ in „Windows“ • Application should adapt Scaling:
› Windows size › Navigationpanel size (if exists) › Icon size, Toolbars, Menus › Fonts, Textfield length › Tree › Etc.
The Goal
SWT
› SWT Standard-Widgets › native Widgets of the Operation System › Fonts are scaled › Sizes (mostly) correct ?? › Images are partially scaled
› OS Images are scaled (e.g. Button with Arrow)
› Custom Images (gif, png) are NOT scaled (e.g. Tree Images)
› SWT Standard-Layouts (i.e. GridLayout, FormLayout etc.)
› Uses information from the SWT Widgets › Sizes are not scaled
› i.e. widthHint, horizontalIndent
Eclipse
100 % 150 %
- Size Icon in Tree - Size Toolbar Icon
Eclipse
Windows 7 Windows 8.1
100 % 500 %
- Tree icons - Toolbar icons
Eclipse
500 %
SWT
› Eclipse
Eclipse
150 %
Eclipse
150 %
SWT
› JFace › Dialog
› convertHorizontalDLUsToPixels(int dlus)
› PixelConverter › Uses static methods
from Dialog class
SWT
› Eclipse Riena › Framework for Enterprise Client/Server Application › Based on OSGi, RCP, SWT › Enduser Driven Navigation Concept
› Navigationtree › Widgets / Ridgets Abstraktion
Riena (before)
Image Size
Width Textfield
Width Text
150 %
Step 1 (Utility)
• SwtUtilities › Point getDpi()
› Display.getDpi() › getDpiFactors() › convertXToDpi(int) › …
• Converts absolute to DPI scaled
• DPI factors
SWT (Utility)
100 % = 96 DPI = 1.0. 125 % = 120 DPI = 1.25 133 % = 128 DPI = 1.33 150 % = 144 DPI = 1.5 200 % = 192 DPI = 2.0 300 % = 288 DPI = 3.0
Note: DPI Factors could be different for X and Y but the Windows API underneath always delivers the same values for X and Y.
Step 2 (Layout)
• GridLayout › DpiGridLayout
› Copy of GridLayout* › Scales values internally - widthHint - horizontalIndent - marginWidth - …
› GridData (internally converted to DpiGridData)
› Swap GridLayout with DpiGridLayout in Riena Applications
› DpiGridLayoutFactory
Note: *GridLayout is final -> Eclipse Bug #443008
Step 2 (Layout - example)
setLayoutData(GridData data)
• On „parent.layout()“ the DpiGridlayout converts GridData into DpiGridData and stores it with setData(..., DpiGridData x)
Step 2 (Layout)
› Layout › Other scalable Layouts
› DpiTableColumnLayout › AbstractDpiColumnLayout extends AbstractColumnLayout
› DpiTableLayout extends TableLayout
› Not yet implemented scaling › RowLayout › FormLayout › FillLayout › …
Layout
Step3 (Icons and Images)
› Images › „Scaling“
› One Image – several Scaling Levels
› One PNG per Level
Skalierung Größe Suffix
100 % 16x16 px 00
125 % 20x20 px 01
133 % 21x21 px 02
150 % 24x24 px 03
Step3 (Icons and Images)
• ImageStore.getImage(„0022a“); • getDpiFactor() -> 1 -> suffix = „00“ • Search for „0022a00.png“ • Return SWT Image object
Note: ImageStore is a class in Riena // always „png“ if no extension is given
Step3 (Images „extended“)
0022a_p_00.png
Actual image names can be more complex in Riena
0022 = image name a = image size(a=16x16, b=22x22 etc.) _p_ = image state (_p_= „pressed“, _d_ = „disabled“ 00 = dpi scale factor (00 = 100% etc)
id = iconManager.getIconID(„0022“, IconSize.A16, IconState.PRESSED); image = ImageStore.getInstance().getImage(id); // implicit adds dpi scale factor „00“
Riena (after)
150 %
Riena internal
› Width and Height of Shell › Width of Navigationtree › Checkboxes in tables (not in column 1) › Statusbar › PopupList with UIProcess (Jobs) › InfoFlyout
• DPI Factors get larger and larger • Many different images for the various levels • Use vector graphics and scale at runtime ? • SVG ?
Step 4: More Scaling
• Image as SVG › Vectorgraphics – stepless – limitless › Not directly supported by SWT › Using SVG Salamander
› https://svgsalamander.java.net/ › SVG -> AWT Image › AWT Image -> SWT Image › converted SWT Images are cached
Step 4: More Scaling
• Image as SVG › Can be used for
› Image Sizes (a,b,c,d,e,f) › Image Scaling (00,01,02,03)
› ONE Image per State
Step 4: More Scaling
id = iconManager.getIconID(„cloud“, IconSize.A16); image = ImageStore.getInstance().getImage(id);
Pitfalls
› Getting the DPI factor › Only in UI Thread
› Rounding problems when scaling › Round up / down
› Distinguish scaled numbers from unscaled numbers
› E.g. Layout › GridData.widthHint › DpiGridLayout
Roundup
SWTUtilities Riena
Scaling
Layouts DpiGridLayout Images
Icons
Scaling Levels
SVG
DpiTableColumnLayout
ImageFactory
Thank you