Posts Tagged ui

LWUIT – een lichtgewicht ui toolkit voor Java ME

Introductie

Ooit al eens een Java ME applicatie ontwikkeld voor een specifiek type mobiele telefoon? Wanneer het aankomt op het ontwikkelen van een gelikte interface loop je er al snel tegen aan dat de MIDP implementatie van de telefoon van invloed is op hoe de widgets van de applicatie getoond worden. Nadeel daarvan is dat de UI er op een ander type mobiel nogal anders uit kan zien. Om die reden was men voorheen nog wel eens geneigd om wat dieper in de code te duiken en de wat specifiekere (geliktere) widgets op de (javax.microedition.lcdui.)Canvas uit te werken. Deze Canvas ondersteunt sinds MIDP-2.0 een fullscreen modus: het is mogelijk om de complete applicatie direct op Canvas te ontwikkelen. Hiervan maakt LWUIT gebruik.

Mogelijk, maar wel bijzonder tijds-intensief, tenzij je gebruik maakt van het werk van anderen die al wat voorwerk hebben verricht op dit gebied. Een mooi voorbeeld hiervan is “LWUIT”, een door Sun ontwikkelde open-source UI toolkit. In tegenstelling tot het ontwerpen van UI’s met standaard Java ME is het met LWUIT mogelijk om op een Swing-achtige manier user interfaces te maken: layout managers, maar ook de pluggable look & feel, het MVC concept en “lightweight componenten” (componenten maken geen gebruik van de native UI controls, maar verzorgen zelf hun rendering en event handling) zijn terug te vinden.

Setup simpele MIDlet

Een MIDlet maken waarin met LWUIT een paar knoppen wordt getoond is simpel voor elkaar te krijgen via de volgende stappen:

  • Download NetBeans (kies een versie met ‘Java ME’ support) en installeer het pakket.
  • Download en unzip de LWUIT zip file (via de ‘Download page’ tab – de zip bevat ook de resource editor).
  • Download en installeer de Sprint wireless toolkit (via de ‘Develop’ tab, de ‘Technologies’ link en dan de ‘Java ME’ link) of een andere toolkit, zoals die van Sun.
  • Binnen NetBeans is het handig om de LWUIT jar toe te voegen als library via ‘Tools’, ‘Libraries en dan de ‘New Library…’ knop. Geef naam, type = ‘Class Libraries’, dan: ‘OK’ en ‘Add JAR/Folder…’: en selecteer het bestand “LWUIT.jar” dat te vinden is in de ‘lib’ dir van de LWUIT installatie (unzippen van de zip file). Het ‘LWUIT_stripped.jar’ bestand is de LWUIT library zonder code die gebruik maakt van JSR 184 (M3G: Mobile 3D Graphics), JSR 75 (PIM: Personal Information Management, FC: File Connection) of JSR 226 (SVG: Scalable 2D Vector Graphics).

    Start vervolgens een nieuw project, kies als categorie ‘Java ME’ en als project ‘Mobile Application’ en druk op ‘Next’. Het is niet nodig om NetBeans een default MIDlet aan te laten maken; het vinkje bij ‘Create Hello MIDlet’ mag weg. Druk weer op ‘Next’. Selecteer de WTK die je hebt geïnstalleerd als ‘Emulator Platform’. LWUIT vereist minimaal MIDP-2.0 bovenop CLDC-1.1, dus i.p.v. MIDP-2.1 die default geselecteerd is zou je MIDP-2.0 kunnen kiezen, maar dit hoeft niet. Druk op ‘Finish’. Maak nu een nieuwe MIDlet aan met de naam ‘MyMIDlet’ en kopieer de volgende code er naartoe:

    import com.sun.lwuit.*;
    import com.sun.lwuit.events.ActionEvent;
    import com.sun.lwuit.layouts.BoxLayout;
    import javax.microedition.midlet.MIDlet;
    
    public class MyMIDlet extends MIDlet {
    
        Form form1;
    
        public void startApp() {
            Display.init(this);
            form1 = new Form("LWUIT Demo Form");
            form1.addCommand(new Command("Quit") {
                public void actionPerformed(ActionEvent ae) {
                    destroyApp(true);
                    notifyDestroyed();
                }
            });
    
            form1.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
            Button l = new Button("Left");
            l.setAlignment(Label.LEFT);
            Button r = new Button("Right");
            r.setAlignment(Label.RIGHT);
            Button m = new Button("Middle");
            m.setAlignment(Label.CENTER);
            form1.addComponent(l);
            form1.addComponent(r);
            form1.addComponent(m);
    
            form1.show();
        }
    
        public void pauseApp() {
        }
    
        public void destroyApp(boolean unconditional) {
        }
    }
    

    Omdat het project de LWUIT jar nog niet kent zal je een aantal foutmeldingen zien: via de project properties kan je onder de ‘Build’ categorie ‘Libraries & Resources’ kiezen. Voeg de LWUIT library die je eerder hebt aangemaakt toe. Omdat er slechts 1 MIDlet in het project zit zal deze MIDlet automatisch gestart worden wanneer je het project right-clickt en dan ‘Run’ selecteert. Het resultaat hiervan is een simpele LWUIT applicatie met een paar knopjes!

    MVC

    Een aardige illustratie van het MVC concept bij LWUIT is de List. Voeg het volgende stuk code in voor de ‘form1.show()’ uit het vorige voorbeeld.

    String[] bands = new String[]{
        "AC/DShe",
        "Public Enema",
        "Beverly Beerbellies",
        "Shirley Temple Pilots",
        "Wynona Riders"};
    List list = new List(bands);
    form1.addComponent(list);
    

    .

    Resultaat

  • Het Model is verantwoordelijk voor de data; zaken als hoeveel items er zijn, maar ook bijvoorbeeld welk item welke offset heeft. Wanneer er veranderingen in het model optreden geeft het model een seintje richting alle (geregistreerde) SelectionListener en DataChangedListener implementaties. De List in dit voorbeeld krijgt een array van Strings aangeleverd en maakt onder water gebruik van een default implementatie van de ListModel interface, het DefaultListModel.
  • De View wordt in dit geval grotendeels geregeld door een default implementatie van de ListCellRenderer (LCR), de DefaultListCellRenderer. De View is verantwoordelijk voor het tonen van de data die het Model levert. De LCR rendert het object dat vanuit het Model wordt geleverd naar een com.sun.lwuit.Component object dat vervolgens door de List wordt gebruikt om zichzelf te renderen. De default implementatie (is-a com.sun.lwuit.Label) doet simpelweg een toString() van het aangeleverde object, zet dit als text op zichzelf en geeft this terug.
  • Tot slot is de List zelf de Controller (en eigenlijk ook een beetje van de View – maakt zwaar gebruik van de LCR, maar rendert uiteindelijk toch zichzelf) die user input afhandelt. Wanneer bijvoorbeeld een ander element in de lijst wordt geselecteerd, dan geeft de List dit door aan het model (die vervolgens weer de geregistreerde SelectionListener objecten triggert).
  • Zelf de implementatie van ListModel en ListCellRenderer verzorgen heeft als extra voordeel dat je de reeds bestaande data types direct kan gebruiken en er geen sprake hoeft te zijn van “state copying”: er is geen voorbepaald data type wat in de List past.

    Ook goed om te weten is dat de List z’n Model alleen maar vraagt naar de data-elementen die op het scherm zichtbaar zijn. Dit (performance) aspect wordt belangrijker naarmate de hoeveelheid data groeit of bijv. vanaf een remote locatie moet worden binnengehaald.

    Conclusie

    Via de bovenstaande stappen is het relatief makkelijk om snel een simpele LWUIT applicatie te maken. Met name voor de ontwikkelaars die hun app op meerdere typen mobiele telefoons willen draaien zal het een aangename verrassing zijn om te zien dat deze voorbeeld-applicatie op alle mobieltjes (die MIDP-2.0/CLDC-1.1 supporten) in uiterlijk en gedrag hetzelfde zal zijn. In een volgende blog zal ik wat verder ingaan op “fancier features” zoals Transitions en Theming; het oog wil immers ook wat!

    , , , , ,

    No Comments

    Flex vs Java Deel 1: Stijlen

    <h2>Inleiding</h2> <p> De veronderstelling is dat je met Flex sneller een gelikte UI in elkaar kunt zetten, maar is dat ook echt zo? Misschien voor een simpel “hello world” appje, maar hoe zit het met complexere UI’s met “custom” vormgeving? </p> <p> In dit eerste deel van de vergelijking tussen Java en Flex zullen we ons richten op de mogelijkheden die Java i.c.m. de Synth LAF en Flex bieden om componenten te skinnen. </p> <h2>Skinnen in Flex</h2> <p> In Flex kan skinnen van componenten op twee manieren: direct in de MXML declaratie van een component of in aparte stylesheets. Skinnen met behulp van stylesheets heeft als voordeel herbruikbaarheid, en wordt daarom ook gezien als best practice.<br/> Stylesheets in Flex lijken verdacht veel op de <a href=”http://www.w3.org/Style/CSS/”>W3C CSS</a>; niet ontoevallig dat Adobe ze ook bij die naam noemt.<br/> Er zijn echter wat aspecten die afwijken van de W3C standaard, en specifiek met betrekking tot selectors: <ul> <li>Geen ondersteuning voor ID selectors. Hiermee kan je in CSS een selector voor een specifiek element declareren, b.v. <code>#pageTitle</code></li> <li>Geen ondersteuning voor nesting selectors. Hiermee kan je alle elementen binnen een ander element selecteren. Voorbeeld: <code>ul a</code>, alle links binnen een unordered list</li> <li>Geen ondersteuning voor pseudo-classes. Meest bekende pseudo-selector is <code>a:hover</code>, waarmee je een de stilering van een link waar de muispointer op ligt kan definiëren</li> </ul> </p> <p> Laten we om te beginnen eens kijken hoe het skinnen werkt als je dat direct op in de component declaratie doet. Als voorbeeld maken we een knop: <pre> &lt;mx:Button label=”Click Me” fontFamily=”Georgia” fontSize=”20″ fontStyle=”italic” textDecoration=”underline” color=”#0000FF”/&gt; </pre> Zoals eerder vermeld, om alle stileringsinformatie op de componenten zelf te plaatsen zou nogal wat werk kosten. Welnu, een klein voorbeeld van hoe dezelfde skin er in Flex CSS uitziet: <pre> Button { color: #0000FF; fontFamily: Georgia; fontSize: 20; fontStyle: italic; textDecoration: underline; } </pre> </p> <p> <div><object classid=”clsid:D27CDB6E-AE6D-11cf-96B8-444553540000″ codebase=”https://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0″ data=”/roller/luminis/resource/flexvsjava/ButtonExample.swf” height=”60″ type=”application/x-shockwave-flash2-preview” width=”200″ ><param name=”data” value=”/roller/luminis/resource/flexvsjava/ButtonExample.swf”/><param name=”loop” value=”false”/><param name=”menu” value=”false”/><param name=”movie” value=”/roller/luminis/resource/flexvsjava/ButtonExample.swf”/><param name=”quality” value=”high”/><param name=”scale” value=”exactfit”/><param name=”src” value=”/roller/luminis/resource/flexvsjava/ButtonExample.swf”/><param name=”type” value=”application/x-shockwave-flash2-preview”/><embed height=”60″ pluginspage=”https://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash” quality=”high” src=”/roller/luminis/resource/flexvsjava/ButtonExample.swf” type=”application/x-shockwave-flash2-preview” width=”200″ /></object></div> </p> <p> Voor diegenen die vaker met HTML en CSS werken zal het redelijk bekend voorkomen. Nu een wat geavanceerder voorbeeld: <pre> Button { color: #0080c0; font-size: 12; corner-radius: 10; border-color: #006699; border-thickness: 3; fill-colors: #FCFFF4, #006699; fill-alphas: 0.5, 0.5; text-roll-over-color: #FFFFFF; } </pre> </p> <p> <div><object classid=”clsid:D27CDB6E-AE6D-11cf-96B8-444553540000″ codebase=”https://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0″ data=”/roller/luminis/resource/flexvsjava/AdvancedButtonExample.swf” height=”60″ type=”application/x-shockwave-flash2-preview” width=”150″ ><param name=”data” value=”/roller/luminis/resource/flexvsjava/AdvancedButtonExample.swf”/><param name=”loop” value=”false”/><param name=”menu” value=”false”/><param name=”movie” value=”/roller/luminis/resource/flexvsjava/AdvancedButtonExample.swf”/><param name=”quality” value=”high”/><param name=”scale” value=”exactfit”/><param name=”src” value=”/roller/luminis/resource/flexvsjava/AdvancedButtonExample.swf”/><param name=”type” value=”application/x-shockwave-flash2-preview”/><embed height=”60″ pluginspage=”https://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash” quality=”high” src=”/roller/luminis/resource/flexvsjava/AdvancedButtonExample.swf” type=”application/x-shockwave-flash2-preview” width=”150″ /></object></div> </p> <p> Hier wordt al meteen duidelijk dat Flex een rijk scala aan stijl- en effectattributen biedt, o.a. voor hoekafrondingen, meerdere kleuren van borders, gradients, transparantie. Tevens is hier te zien dat het ontbreken van pseudo-selectors wordt opgevangen door attributen als <code>overFillColors</code>, <code>selectedFillColorRatios</code>, enz. </p> <p> Toewijzen van stijlen aan componenten in Flex kan op de volgende manieren: <ul> <li>Door middel van type selectors: de naam van de componentklasse wordt als selector gedefinieerd.</li> <li>Door middel van class selectors: een component een stijlnaam te geven, die vervolgens als selector in de style sheet te declareren.</li> </ul> Overigens zijn combinaties van bovenstaande methodes ook mogelijk, hierover later meer. </p> <h3>Type selectors</h3> <p> Indien we voor een componentklasse een stijl willen definieren, hoeven we slechts zijn naam als CSS selector met de bijbehorende stijlattributen te declareren: <pre> Button { color: red; cornerRadius: 12; textSize: 12; } Label { color: black; } </pre> </p> <p> Een leuk aspect is de manier waarop componentovererving is verweven met stijldefinities. Nemen we als voorbeeld de <code>Text</code> klasse: deze erft van <code>Label</code>, en erft ook alle gedefinieerde stijlelementen van <code>Label</code>. <pre> Label { color: red; cornerRadius: 12; textSize: 12; } Text { color: black; } </pre> </p> <h3>Class selectors</h3> <p> De andere manier om stijlkoppelingen te bewerkstelligen is een stijl direct toewijzen een component, d.m.v. een zogenaamde class selector.<br/> Neem het volgende code fragment: <pre> .myButton { color: red; textSize: 12; } </pre> <pre> &lt;mx:Button styleName=”myButton” label=”OK”/&gt; </pre> </p> <p> Zoals eerder vermeld, zijn type selectors en class selectors ook te combineren. Type selectors worden toegepast op alle instanties van een component klasse, maar daarnaast kan een instantie van een component klasse ook een eigen stijl selecteren. De gedeclareerde attributen in deze stijl zullen alle attributen overschrijven die in de type selector staan. Als voorbeeld: <pre> Button { color: yellow; textSize: 12; } .myButton { color: red; } </pre> <pre> &lt;mx:Button label=”Cancel”/&gt; &lt;!– Gele tekst –&gt; &lt;mx:Button styleName=”myButton” label=”OK”/&gt; &lt;!– Rode tekst –&gt; </pre> </p> <h2>Java Synth LAF</h2> <p> De Java Synth LAF is, zoals de naam al zegt, een Pluggable Look & Feel implementatie voor Swing. Dit wil ook zeggen dat Synth niet per definitie als skin voor een applicatie wordt gebruikt, maar dat deze, zoals alle Swing Look and Feels, eerst geïnstalleerd moet worden. <pre> URL file = …; // De URL naar de Synth style file SynthLookAndFeel synth = new SynthLookAndFeel(); try { synth.load(file); UIManager.setLookAndFeel(synth); } catch (Exception e) { e.printStackTrace(); } </pre> </p> <p> Een van de dingen die al meteen opvallen is dat Synth LAF een referentie naar een bestand nodig heeft. Dit is een bestand waar alle stijlen zijn gedefiniëerd; Synth heeft namelijk geen ‘default’ skin, dus de aanweizigheid van dit bestand is vereist. </p> <p> Wat staat er nou in zo’n Synth stijl bestand? Hier een klein voorbeeld: <pre> &lt;synth&gt; &lt;color id=”fg_color” value=”#00364e”/&gt; &lt;color id=”bg_color” value=”#0f79a9″/&gt; &lt;font id=”std_font” name=”Arial” size=”12″ style=”PLAIN”/&gt; &lt;style id=”default”&gt; &lt;font idref=”std_font/&gt; &lt;state&gt; &lt;color idref=”fg_color” type=”FOREGROUND”/&gt; &lt;color idref=”bg_color” type=”BACKGROUND”/&gt; &lt;/state&gt; &lt;/style&gt; &lt;bind style=”default” type=”region” key=”.*”/&gt; &lt;!– … overige stijlen… –&gt; &lt;/synth&gt; </pre> Dit is een voorbeeld van een Synth Style bestand in zijn meest kale vorm: er wordt alleen een standaard stijl gegeven die geldt voor alle componenten. Aan deze stijl wordt gekoppeld een voor- en achtergrondkleur en een font.<br/> Een interessant detail aan dit voorbeeld is dat het illustreert hoe stijlelementen, zoals kleuren en lettertypen, herbruikt kunnen worden. <br/> De functie van het bind element behandelen we verderop. </p> <p> Nu naar een wat ingewikkelder component, een button: <pre> &lt;style id=”defaultbutton”&gt; &lt;state id=”def”&gt; &lt;imagePainter method=”buttonBackground” path=”button_up.png” sourceInsets=”8 8 8 8″ paintCenter=”true” /&gt; &lt;insets top=”8″ left=”8″ bottom=”8″ right=”8″ /&gt; &lt;font name=”Arial” size=”12″ style=”BOLD” /&gt; &lt;color value=”#000000″ type=”TEXT_FOREGROUND” /&gt; &lt;/state&gt; &lt;state value=”PRESSED”&gt; &lt;imagePainter method=”buttonBackground” path=”button_pressed.png” sourceInsets=”8 8 8 8″ paintCenter=”true” /&gt; &lt;insets top=”8″ left=”8″ bottom=”8″ right=”8″ /&gt; &lt;/state&gt; &lt;state value=”MOUSE_OVER”&gt; &lt;imagePainter method=”buttonBackground” path=”button_over.png” sourceInsets=”8 8 8 8″ paintCenter=”true” /&gt; &lt;insets top=”8″ left=”8″ bottom=”8″ right=”8″ /&gt; &lt;/state&gt; &lt;state value=”DISABLED” clone=”def”&gt; &lt;color value=”#999999″ type=”TEXT_FOREGROUND” /&gt; &lt;/state&gt; &lt;/style&gt; &lt;bind style=”defaultbutton” type=”region” key=”BUTTON”/&gt; </pre> </p> <p> <applet code=”ButtonStyleExample.class” codebase=”.” archive=”/roller/luminis/resource/flexvsjava/flexvsjavastyles.jar” width=”300″ height=”100″></applet> </p> <p> In dit voorbeeld zijn eigenlijk al bijna alle kernconcepten van de Synth Style vervat. Een Synth Style bestand bevat een of meerdere style declaraties, die een unieke identificatie hebben (het id attribuut). Een style slaat in de praktijk op de skin van een specifieke componentklasse, in dit voorbeeld buttons. </p> <p> Binnen een style worden een of meerdere states gedefiniëerd. Een state is ook letterlijk de toestand waarin het component zich bevindt. In dit voorbeeld zijn een viertal states gedefinieerd: de standaard wanneer er niets bijzonders met het component gebeurt, wanneer hij ingedrukt wordt (<code>PRESSED</code>), wanneer hij disabled is (<code>DISABLED</code>) en wanneer de mousepointer er over zweeft (<code>MOUSE_OVER</code>). Overige beschikbare states zijn: <code>ENABLED</code>, <code>FOCUSSED</code>, <code>SELECTED</code>, <code>DEFAULT</code>. </p> <p> Een state bevat de stijlattributen van een component in een specifieke toestand. DIt kunnen zijn kleuren voor de voor- of achtergrond (het <code>color</code> element), lettertypes voor tekst (het <code>font</code> element), afbeeldingen (het <code>imagePainter</code> element), en de grensruimte van een component (het <code>insets</code> element). </p> <p> Overerving van stijlen is ook mogelijk, en wel door middel van het clone attribuut binnen het style element. <pre> &lt;style id=”textfield”&gt; &lt;state&gt; &lt;color value=”yellow” type=”BACKGROUND”/&gt; &lt;color value=”blue” type=”TEXT_FOREGROUND”/&gt; &lt;font name=”Arial” size=”14″ style=”BOLD” /&gt; &lt;insets top=”4″ left=”4″ bottom=”4″ right=”4″ /&gt; &lt;/state&gt; &lt;/style&gt; &lt;style id=”passwordfield” clone=”textfield”&gt; &lt;state&gt; &lt;color value=”orange” type=”BACKGROUND”/&gt; &lt;color value=”black” type=”TEXT_FOREGROUND”/&gt; &lt;/state&gt; &lt;/style&gt; &lt;bind style=”textfield” type=”region” key=”TextField”/&gt; &lt;bind style=”passwordfield” type=”region” key=”PasswordField”/&gt; </pre> </p> <p> <applet code=”TextFieldStyleExample.class” codebase=”.” archive=”/download/attachments/14812620/flexvsjavastyles.jar” width=”300″ height=”100″></applet> </p> <p> In Java Synth wordt een stijl gekoppeld aan een component door middel van het bind element. Dit element biedt de mogelijkheid om een stijl te binden aan een component. Het bind element heeft 3 attributen die van belang zijn: <ul> <li><code>style</code>: de referentie naar een elders gedeclareerde stijl</li> <li><code>type</code>: de soort koppeling, d.w.z. generieke of specifieke koppeling</li> <li><code>key</code>: de sleutel van de koppeling, d.w.z. de naam van een component of de naam van de klasse.</li> </ul> </p> <p> Beginnend met de declaratie van een stijl: <pre> &lt;style id=”buttonStyle”&gt;…&lt;/style&gt; </pre> Een bind element moet in ieder geval een referentie hebben naar de gedeclareerde stijl, in dit geval <code>buttonStyle</code>: <pre> &lt;bind style=”buttonStyle” … /&gt; </pre> Als voorbeeld willen we alle knoppen in onze applicatie binden aan de stijl <code>buttonStyle</code>. Dit doen we door als type attribuut ‘region’ op te geven, en als key attribuut een van de constanten uit de <code>javax.swing.plaf.synth.Region</code> klasse te gebruiken, in dit geval de waarde van <code>javax.swing.plaf.synth.Region.BUTTON</code>: <pre> &lt;bind style=”buttonStyle” type=”region” key=”Button” /&gt; </pre> </p> <p> Om een enkel component een afwijkende stijl te geven is wat meer werk nodig. Nu vertellen we de binding dat het moet kijken naar componenten die een specifieke naam hebben. Als voorbeeld maken we een binding die de stijl <code>buttonStyle</code> koppelt aan componenten met naam <code>XXX</code>: <pre> &lt;bind style=”buttonStyle” type=”name” key=”XXX” /&gt; </pre> Met deze binding hebben we in feite nog niets gekoppeld. Dit gebeurt pas als er een component wordt aangemaakt die <code>XXX</code> als naam heeft: <pre> JButton b = new JButton(”Klik mij”); b.setName(”XXX”); </pre> </p> <p> Een leuke feature van binden is dat er ook reguliere expressies gebruikt kunnen worden. Bijvoorbeeld: <pre> &lt;bind style=”knopStijl” type=”name” key=”knop.*” /&gt; </pre> Dit bindt alle componenten wiens naam begint met <code>knop</code> aan de stijl <code>knopStijl</code>. </p> <p> Een ander aspect van stijl koppelingen in Synth is dat er meerdere stijlen gebonden kunnen worden aan componentent. Neem de volgende stijldeclaraties en bindings: <pre> &lt;style id=”Globaal”&gt; &lt;state&gt; &lt;color value=”blue” type=”FOREGROUND”/&gt; &lt;/state&gt; &lt;/style&gt; &lt;style id=”Knop”&gt; &lt;state&gt; &lt;color value=”orange” type=”FOREGROUND”/&gt; &lt;/state&gt; &lt;/style&gt; &lt;style id=”SpecialeKnop”&gt; &lt;state&gt; &lt;color value=”red” type=”BACKGROUND”/&gt; &lt;/state&gt; &lt;/style&gt; &lt;bind style=”Globaal” type=”region” name=”*”/&gt; &lt;bind style=”Knop” type=”region” name=”Button”/&gt; &lt;bind style=”SpecialeKnop” type=”name” name=”speciale_knop.*”/&gt; </pre> Bovenstaande code geeft alle componenten een gele tekstkleur, behalve knoppen die een blauwe tekstkleur krijgen. Indien de naam van een knop (die reeds de <code>Knop</code> stijl heeft) begint met <code>speciale_knop</code>, zal deze ook de stijl <code>SpecialeKnop</code> toegewezen krijgen, wat inhoudt dat de achtergrond rood wordt. </p> <h2>Een vergelijking in de praktijk</h2> <p> Welnu, een praktijk voorbeeldje. We stellen ons als opdracht: het maken van een button met afgeronde hoeken en een achtergrond met een verticale 2-kleuren gradient (wit en groen). Tevens heeft de button een mouse-over effect waarbij de tweede gradient kleur wijzigt naar donkergroen. </p> <h3>Implementatie in Flex</h3> <p> In Flex is dit een fluitje van een cent. Om te beginnen met de ronde hoeken, welke te verwezenlijken zijn met het ‘corner-radius’ stijl attribuut: <pre> Button { cornerRadius: 12; /* De mate van afronding */ } </pre> Vervolgens de gradient, waar een tweetal stijattributen van belang zijn: fillColors en fillColorRatios. Het eerst attribuut definieert de kleuren, het tweede de relatieve posities (op een schaal van 0 tot 255) waar maximale verzadiging is. <pre> Button { cornerRadius: 12; /* De mate van afronding */ fillColors: #FFFFFF, #00FF00; /* wit, groen */ fillColorRatios: 0, 255; } </pre> Ten slotte het mouse-over effect, waarbij de overFillColors en overFillColorRatios worden gebruikt. <pre> Button { cornerRadius: 12; /* De waarde geeft de mate van hoekafronding */ fillColors: #FFFFFF, #33FF00; /* wit, groen */ fillColorRatios: 0, 255; overFillColors: #FFFFFF, #00CC00; /* wit, donkergroen */ overFillColorRatios: 0, 255; } </pre> </p> <p> <div><object classid=”clsid:D27CDB6E-AE6D-11cf-96B8-444553540000″ codebase=”https://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0″ data=”/roller/luminis/resource/flexvsjava/ButtonGradientExample.swf” height=”60″ type=”application/x-shockwave-flash2-preview” width=”150″ ><param name=”data” value=”/roller/luminis/resource/flexvsjava/ButtonGradientExample.swf”/><param name=”loop” value=”false”/><param name=”menu” value=”false”/><param name=”movie” value=”/roller/luminis/resource/flexvsjava/ButtonGradientExample.swf”/><param name=”quality” value=”high”/><param name=”scale” value=”exactfit”/><param name=”src” value=”/roller/luminis/resource/flexvsjava/ButtonGradientExample.swf”/><param name=”type” value=”application/x-shockwave-flash2-preview”/><embed height=”60″ pluginspage=”https://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash” quality=”high” src=”/roller/luminis/resource/flexvsjava/ButtonGradientExample.swf” type=”application/x-shockwave-flash2-preview” width=”150″ /></object></div> </p> <h3>Implementatie in Java Synth LAF</h3> Hier lopen we al meteen tegen 2 issues aan: Synth LAF heeft geen ondersteuning voor afgeronde hoeken in componenten (de zogenaamde corner radius) en gradients. In principe is een gradient achtergrond wel te maken, maar dit kost wat werk. Eerst moeten we een painter coderen die gradients kan maken: <pre> public class GradientPainter2 extends SynthPainter { public void paintTextFieldBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { GradientPaint gp = new GradientPaint((float)(x + (w/2)), (float)y, Color.WHITE, (float)(x + (w/2)), (float)(y + h), new Color(0, 200, 0)); Graphics2D g2 = (Graphics2D)g; g2.setPaint(gp); g2.fillRect(x, y, w, h); g2.setPaint(null); } } </pre> Vervolgens declareren we deze in de Synth configuratie als een object, en maken een painter op basis van dit object: <pre> &lt;object id=”gradient”/&gt; &lt;style id=”button”&gt; &lt;painter method=”buttonBackground” idref=”gradient”/&gt; &lt;/style&gt; </pre> Hiermee hebben we helaas nog geen afgeronde hoeken. Een andere taktiek is dus vereist. De simpelste methode is het maken van achtergrondafbeeldingen die de gradient en afgeronde hoeken al hebben. Deze afbeeldingen worden door Synth geschaald op de grootte van de button <pre> &lt;style id=”button”&gt; &lt;state&gt; &lt;imagePainter method=”buttonBackground” path=”buttonUp.png” sourceInsets=”8 8 8 8″ paintCenter=”true”/&gt; &lt;/state&gt; &lt;state value=”MOUSE_OVER”&gt; &lt;imagePainter method=”buttonBackground” path=”buttonDown.png” sourceInsets=”8 8 8 8″ paintCenter=”true”/&gt; &lt;/state&gt; &lt;/style&gt; </pre> Interessant om te vermelden is dat de bovenstaande methode met achtergrondafbeeldingen ook in Flex toegepast kan worden: <pre> Button { up-skin: Embed(source=”buttonUp.png”); over-skin: Embed(source=”buttonDown.png”); } </pre> <h2>Conclusie</h2> <p> Als we de twee implementaties nu vergelijken, valt meteen op dat Synth erg afhankelijk is van externe graphics wil er een beetje leuk resultaat uit komen. Dit heeft tot gevolg dat er een grote afhankelijkheid op een designer is, en dat de grootte van de applicatie aanzienelijk toeneemt door alle extra graphics die erbij komen. </p> <p> Flex daarentegen biedt een developer wat meer ruimte en mogelijkheden om in de loop van een ontwikkeltraject zelf nog aanpassingen te kunnen doen. Hierbij moet opgemerkt worden dat bij ieder nadeel weer en voordeel zit: indien er voor wordt gekozen om de skin volledig met externe graphics op te bouwen, vereist het minder vaardigheden van de designer, die zich niet bezig hoeft te houden met MXML en/of Actionscript. </p> <p> Wel is het zo dat skins in Synth op een veel consistentere manier zijn op te bouwen. Vrijwel alle stijlelementen zijn herbruikbaar, dus er zullen minder snel foutjes insluipen. Tevens heeft dit tot gevolg dat skin refactorings (denk aan verandering van fonts of kleuren) een relatief eenvoudige operatie zullen zijn. Dit zou in Flex toch wat meer aandacht en tijd kosten, aangezien CSS geen hergebruik (anders gezegd: centrale declaratie) van stijlelementen mogelijk maakt. </p> <p> Wat verder opvalt is dat de de hoeveelheid CSS code voor een Flex applicatie t.o.v. Synth Style bestand vele malen compacter is. </p>


    , ,

    No Comments