next up previous contents
Nästa: 4.6 Övningar Upp: 4. Fönstersystemet X Förra: 4.4 Resurser

  
4.5 Klasser och objekt

Vi ska i detta avsnitt berätta slutet på sagan om X-resurser.

Ett bra exempel på en X-klient med mer sammansatta objekt är xfontsel. Hela dess fönster betraktas som ett objekt med namnet pane. Detta objekt är sammansatt av fem delobjekt, nämligen commandBox, fieldBox, fontName, viewPort och grip.

Det första delobjektet, commandBox, omfattar den översta raden av fönstret. Detta delobjekt har i sin tur tre delar. En del (med namnet quitButton) är rutan till vänster där det står ''quit''. En annan del (med namnet ownButton) är rutan där det står ''select''. Den tredje och sista delen (med namnet countLabel) är texten längst till höger, den som säger ''4 names match'' i bild 4.4.

Det andra delobjektet, fieldBox, omfattar fönstrets andra rad. Det har i sin tur femton delobjekt. Fjorton av delobjekten (med namnen field0, field1 osv) representerar de olika fälten i en fontsträng. Varje sådant fält föregås av ett streck (eller ett minustecken). Det femtonde delobjektet, med namnet dash, representerar dessa streck. Exempelvis gör resursdefinitionerna

xfontsel.pane.fieldBox.field0.background: Blue
xfontsel.pane.fieldBox.field0.foreground: White
xfontsel.pane.fieldBox.field0.label: varumärke
att fältet längst till vänster blir blått med texten ''varumärke'' i vitt. Prova dem gärna - dvs läs in dem med xrdb och starta sedan en ny xfontsel!

Tredje delobjektet av pane är fontName. Det omfattar tredje raden i xfontsel-fönstret, där den valda fontens namn finns utskrivet.

Det fjärde delobjektet, viewPort, omfattar den nedre halvan av fönstret. I detta fält finns en exempeltext som är skriven med den valda fonten.

Det femte delobjektet, grip, består av de små handtagen till höger i xfontsel-fönstret. Med deras hjälp kan man ändra storleken på de olika delarna av fönstret genom att man flyttar pekaren till någon av dem, håller in musens vänsterknapp och samtidigt flyttar musen uppåt eller nedåt.

Programmet editres kan rita diagram över objektstrukturen för X-klienter. I figur [*] visas en liten del av objektstrukturen för xfontsel. Några attribut för field0 finns också med där.

  
Figur: Del av objektstrukturen för xfontsel.
\begin{figure}
\small \psset{angleB=90, angleA=-90, levelsep=36pt, armB=14pt,
...
...Name}}
\Tr{\psshadowbox{\rule{0pt}{6pt}viewPort}}
}
\end{center}\end{figure}

Antag att vi vill ha vit text och blå bakgrund på alla de fjorton fält som är delobjekt i fieldBox. Det går visserligen att sätta värden för varje fält för sig, på samma sätt som vi gjorde med det första fältet, men det är otympligt. Det finns dock ett smidigare sätt. Varje objekt (och varje delobjekt) tillhör nämligen en klass. En klass innehåller ibland bara ett, ibland flera objekt. De fjorton fälten field0, field1 osv bildar tillsammans en klass med namnet MenuButton. Om vi skriver MenuButton i stället för field0, så gäller definitionen för alla de fjorton fälten. Prova alltså det här:

xfontsel.pane.fieldBox.MenuButton.background: Blue
xfontsel.pane.fieldBox.MenuButton.foreground: White

Klassnamn börjar alltid med stor bokstav, objektnamn börjar aldrig med stor bokstav. Därigenom blir det lätt att skilja mellan klasser och objekt. Detta förklarar den märkliga formen på objektnamn som fieldBox: det måste börja med liten bokstav eftersom det annars skulle se ut som ett klassnamn. När objektnamn är sammansatta av flera ord, tex ''field'' och ''box'', brukar alla orden utom det första skrivas med stor bokstav.

Men om vi nu vill att fälten ska ha blå bakgrund, med undantag för det sjunde fältet som ska ha röd bakgrund för att synas bättre? Det är enkelt, lägg bara till en rad som säger att field6 ska ha röd bakgrund. Om man anger värden både för klassen och för ett enskilt objekt, så gäller det värde man satte för objektet. Detta följer en allmän regel för hur resurser tolkas: om flera olika definitioner påverkar samma attribut, så prioriteras den resurssträng som är mest specifik.

Prova nu att läsa in resursdefinitionerna

xfontsel.pane.fieldBox.MenuButton.background: Blue
xfontsel.pane.fieldBox.MenuButton.foreground: White
xfontsel.pane.fieldBox.field6.background: Red
xfontsel.pane.fieldBox.field6.label: storlek
Följden blir att alla fält utom det sjätte får blå bakgrund och vit text. Det sjätte fältet får röd bakgrund samt texten ''storlek'' i vitt.

Också attributen tillhör klasser. Från utdraget av bruksanvisningen till xclock kan vi se att attributen foreground, hands och highlight alla tillhör klassen Foreground. Definitionen xclock.clock.Foreground: Blue gör att hela förgrunden i xclock, dvs tim- och minutstreck samt visarna, blir blå. Om vi dessutom gör definitionen xclock.clock.hands: Green, så blir det inre av visarna grönt medan tim- och minutstreck samt kanten på visarna förblir blått.

Antag nu att vi vill att hela bakgrunden i xfontsel ska vara blå. Ett sätt att uppnå detta är att ta alla resursvariabler med attribut background och ge dem värdet Blue. Så här blir det då:

xfontsel.pane.commandBox.background: Blue
xfontsel.pane.commandBox.countLabel.background: Blue
xfontsel.pane.commandBox.ownButton.background: Blue
xfontsel.pane.commandBox.quitButton.background: Blue
xfontsel.pane.fieldBox.background: Blue
xfontsel.pane.fieldBox.dash.background: Blue
xfontsel.pane.fieldBox.MenuButton.background: Blue
xfontsel.pane.fontName.background: Blue
xfontsel.pane.viewPort.sampleText.background: Blue
Detta är onödigt komplicerat. Återigen finns ett enklare sätt: man kan använda jokertecknet *. Då räcker det att göra så här:
xfontsel*background: Blue
Som synes i tabell 4.1, så har flaggan -bg Blue exakt samma effekt.

Den första av definitionerna

xfontsel*background: Blue
xfontsel.pane.fieldBox.field6.background: Red
säger att all bakgrund ska vara blå, den andra säger att bakgrunden i sjunde fältet i fontsträngen ska vara röd. Så vilken färg blir det i det sjunde fältet? Jo, den blir röd - helt i linje med principen att den mer specifika definitionen ska ha företräde.

Mycket ofta använder man jokertecknet helt enkelt för att slippa skriva ut objektnamnet - antingen för att man inte orkar kolla upp exakt vad det heter, eller för att det blir för långt att skriva. Så till exempel brukar man föredra

xfontsel*field0.label: varumärke
xfontsel*field6.label: storlek
framför att skriva ut resursvariablernas namn fullständigt. Det finns ytterligare ett skäl till detta: om det kommer en ny version av tex xclock, så kanske man lägger in ytterligare någon nivå i objekthierarkin - kanske nivån face mellan clock och attributet. I så fall ändras resursvariablernas namn, till xclock.clock.face.hands osv. Då fungerar fortfarande xclock*hands, och man slipper göra ändringar i sina resursfiler.

 

Vanligtvis är det så att alla egenskaper hos en X-klient som kan ställas in med hjälp av flaggor på kommandoraden, också kan ställas in med hjälp av resurser. Däremot kan man ofta göra saker med resurser som inte går att göra med flaggor.

Två av standardflaggorna från tabell 4.1 har med resurser att göra, nämligen -xrm och -name.

Flaggan -xrm läser helt enkelt in en resursdefinition. Ett exempel är$ xfontsel -xrm 'xfontsel*field6.label: storlek' &
$
Skälet till att man kan behöva använda flaggan -xrm är just att det kan finnas vissa egenskaper som kan ställas in med hjälp av resurser men inte med hjälp av flaggor. Genom att använda -xrm slipper man skriva in resursdefinitionen i en fil.

Flaggan -xrm används inte särskilt ofta. En annan standardflagga, -name, är desto intressantare. I stället för att orda så mycket om den ska vi ge ett exempel. Läs först in definitionerna

xclock.clock.analog: True
xclock.clock.hands: Green
xclock.clock.update: 1
digitalur.clock.analog: False
digitalur.clock.font: -*-courier-bold-r-*--18-*-75-75-m-*-iso8859-1
med hjälp av xrdb. De tre första definitionerna gäller programmet xclock medan de båda sista gäller en X-klient med namnet digitalur. Ge nu kommandona$ xclock &
$ xclock -name digitalur &
$
Vad händer? Jo, först får vi en analog klocka med gröna visare som uppdateras varje sekund. Det andra kommandot ger en digital klocka med den font vi angav i den femte raden ovan. Kommandot xclock -name digitalur & startade en xclock-process, men den fick namnet digitalur istället för xclock. Därigenom gällde de båda sista resursdefinitionerna (i stället för de tre första) för den processen.

Poängen med flaggan -name är att den kan användas som i exemplet ovan. Den behövs då man har två (eller fler) standardkonfigurationer för en viss X-klient, och vill ha än den ena, än den andra konfigurationen. Då ger man helt enkelt varje konfiguration ett namn, som tex digitalur, och tar med flaggan -name digitalur vid de tillfällen då man föredrar just den konfigurationen.

En defekt med digitalklockan är att den bara uppdateras en gång i minuten. Vi skulle vilja att den också uppdateras varje sekund. Raden digitalur.clock.update: 1 ordnar detta. Men det finns ett annat sätt, som vi nu ska beskriva. Vi minns att varje komponent i namnet på en resursvariabel tillhör någon klass. Detta gäller också för den första komponenten i resursvariabeln, dvs klientens namn. Varje X-klient har alltså ett klassnamn.

Varje xclock-process tillhör klassen XClock, oavsett om processen heter xclock, digitalur eller något annat. Detta fungerar precis som då attributen foreground, hands och highlight alla tillhör klassen Foreground.

Om vi läser in definitionerna

xclock*analog: True
xclock*hands: Green
XClock*update: 1
digitalur*analog: False
digitalur*font: -*-courier-bold-r-*--18-*-75-75-m-*-iso8859-1
med xrdb och sedan ger kommandot xclock -name digitalur &, så får vi alltså en digital klocka som uppdateras varje sekund.

Man kan ta reda på klassnamn och klientnamn för ett visst fönster genom att ge kommandot xprop och sedan klicka på fönstret. Då spottas en sida text ut. Texten ger information om fönstret, bla en rad i stil med

WM_CLASS(STRING) = "digitalur", "XClock"
Detta betyder att klientnamnet var digitalur och klassnamnet XClock.


next up previous contents
Nästa: 4.6 Övningar Upp: 4. Fönstersystemet X Förra: 4.4 Resurser
Goran Andersson
1999-03-08