Symbian3/SDK/Source/GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1.dita
changeset 8 ae94777fff8f
parent 7 51a74ef9ed63
child 9 59758314f811
--- a/Symbian3/SDK/Source/GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1.dita	Wed Mar 31 11:11:55 2010 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,552 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
-<!-- This component and the accompanying materials are made available under the terms of the License 
-"Eclipse Public License v1.0" which accompanies this distribution, 
-and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
-<!-- Initial Contributors:
-    Nokia Corporation - initial contribution.
-Contributors: 
--->
-<!DOCTYPE concept
-  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
-<concept id="GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1" xml:lang="en"><title>How
-to write controls</title><prolog><metadata><keywords/></metadata></prolog><conbody>
-<p>Cone itself does not provide any concrete controls. Uikon and the UI variant
-libraries provide a large number of 'stock' controls for application writers.
-Application writers often need to supplement the standard set of controls
-with application specific controls of their own. These may be completely new
-controls or, more often, compound controls which contain a number of standard
-controls. </p>
-<p>This section describes how to create controls and how to integrate them
-in to the control framework. It is divided into the following sections: </p>
-<p><xref href="GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1.dita#GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1/GUID-341017B2-8CF9-5124-8D20-C75A8A51F0B7-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-13">Creating
-a control</xref>  </p>
-<p><xref href="GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1.dita#GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1/GUID-3F0E8223-2218-5C95-AFBC-D66AD1DB12A7-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-14">Window
-owning or not?</xref>  </p>
-<p><xref href="GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1.dita#GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1/GUID-795EBF51-AD26-513E-9A82-A99C629CE779-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-15">Creating
-a compound control</xref>  </p>
-<p><xref href="GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1.dita#GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1/GUID-795EBF51-AD26-513E-9A82-A99C629CE779-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-15">Size,
-position and layout</xref>  </p>
-<p><xref href="GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1.dita#GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1/GUID-351911EE-87C7-5D11-8434-BA7FD3741745-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-17">Drawing
-and refreshing</xref>  </p>
-<p> <xref href="GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1.dita#GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1/GUID-FF7DB067-24AD-50C3-BF52-952F836609B0-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-18">Drawing
-backgrounds</xref>  </p>
-<p> <xref href="GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1.dita#GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1/GUID-54C6A39A-CBD0-52E5-8CD0-76BE22247A54-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-19">Drawing
-text</xref>  </p>
-<p> <xref href="GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1.dita#GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1/GUID-D1AED2A8-94AC-54BB-9CEB-C8C3643AFBBD-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-20">Drawing
-graphics</xref>  </p>
-<p><xref href="GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1.dita#GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1/GUID-AC723EE4-1482-59C5-9F13-CAE119C7800D-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-21">Handling
-events</xref>  </p>
-<p><xref href="GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1.dita#GUID-B84FA223-3DFD-58C5-8CEF-C5AA73AA6290-GENID-1-8-1-6-1-1-4-1-6-1-9-1/GUID-FE221E89-1817-5A73-8FBA-212FBC030766-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-22">Implementing
-the Object Provider (MOP) interface</xref>  </p>
-<section id="GUID-341017B2-8CF9-5124-8D20-C75A8A51F0B7-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-13"><title>Creating a
-control</title> <p>A control is a class which derives from <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita"><apiname>CCoeControl</apiname></xref>.
-It should have a public constructor and, if any leaving function calls or
-memory allocations are required during construction, a <codeph>ConstructL()</codeph> function.
-The majority of re-useable and configurable controls have a <codeph>ConstructFromResourceL()</codeph> function
-which allows a specific instance of a control to be configured using an application's
-resource file. Obviously any memory allocated must be freed in the destructor.
-Before a control is drawn to the screen it must be activated. The <codeph>ActivateL()
-function</codeph> may be overriden to perform last-minute configuration (but
-must call the function in the base class). </p> <codeblock id="GUID-18D48E7E-9846-5CE0-BE1E-FAB723419B90-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-13-3" xml:space="preserve">
-Class CMyControl : public CCoeControl
-    {
-    public:
-        CMyControl() ;
-        void ConstructL(...) ;
-        // from CCoeControl
-        void ConsructFromResourceL( TResourceReader&amp; aReader ) ; 
-    private:
-        ~CMyControl() ;
-
-    // additional functions to handle events 
-    // additional functions to draw the control
-    // additional functions to determine the size, layout and position the control
-    }</codeblock> </section>
-<section id="GUID-3F0E8223-2218-5C95-AFBC-D66AD1DB12A7-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-14"><title>Window owning
-or not? </title> <p>The decision over whether to make a control window owning
-or not is usually straightforward. Each view requires a window, so the top-level
-control must be window-owning and a child of the AppUi. Below this a window
-owning control is normally only necessary where a sense of layering is required:
-for instance a pop-up window or a scrolling window. Dialogs and menus are
-window owning controls but these are normally implemented in the Uikon and
-UI variant libraries and do not require custom derivation from <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita"><apiname>CCoeControl</apiname></xref>.
-Unnecessary window-owning controls should be avoided as they require more
-infrastructure, place greater demand on the Window Server and reduce performance. </p> <p>If
-a control must be window owning its window must either be created in the <codeph>ConstructL()</codeph> function
-or by the caller. The former is preferred. There are several overloads of
-the <codeph>CreateWindowL()</codeph> and <codeph>CreateBackedUpWindowL()</codeph> functions.
-Those which do not take a parent parameter create a top-level window which
-is a child of the root window. </p> <p>If a control is not window owning its <codeph>SetContainerWindowL()</codeph> function
-must be called when it is instantiated. </p> <p>If it can, the Framework will
-automatically set up the parent pointer when the window, or associated window
-relationship is established. If it cannot do this, because <codeph>CreateWindowL()</codeph> or <codeph>SetContainerWindowL()</codeph> did
-not provide a <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita"><apiname>CCoeControl</apiname></xref>, the parent pointer (and MopParent)
-may be set expicitly using <codeph>SetParent()</codeph> and <codeph>SetMopParent()</codeph>. </p> </section>
-<section id="GUID-795EBF51-AD26-513E-9A82-A99C629CE779-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-15"><title>Creating a
-compound control</title> <p>Most applications UIs are built from compound
-controls. Many custom controls are built up from stock controls and are therefore
-also compound controls. When a compound control is constructed it constructs
-its components in its <codeph>ConstructL()</codeph> function. When it receives
-commands itself, such as <codeph>ActivateL()</codeph> and <codeph>DrawNow()</codeph> it
-passes them on to each of its components. In most cases the Framework does
-much of the donkey work as long as the compound control has been constructed
-correctly. </p> <p>There are now two methods of creating and managing lodger
-controls. The first method described is the one that should be used. </p> <codeblock id="GUID-F77661F7-6A68-58DB-B875-9D957A937617-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-15-4" xml:space="preserve">
-void MyControl::ConstructL( ... )
-    {
-    // initialise the component array. This must be called once (subsequent calls have no effect)
-    InitComponentArrayL() ; 
-
-    // construct each component control and add it to the component array.
-    CComponent* myComponent = new (ELeave) CComponent ;
-    Components().AppendLC( myComponent ) ; // or InsertLC or InsertAfterLC().  Places item on cleanup stack.
-    myComponent-&gt;ConstructL() ;
-    myComponent-&gt;SetThisAndThatL() ;
-    CleanupStack::Pop( myComponent ) ;    
-    }</codeblock> <p>The return value of the insert and append methods is
-a <xref href="GUID-2D8BFBA2-79AC-364D-875D-E863CD4A2FE1.dita#GUID-2D8BFBA2-79AC-364D-875D-E863CD4A2FE1/GUID-AD37D86C-F9FA-3514-BFD4-7139A0B8543F"><apiname>CCoeControlArray::TCursor</apiname></xref> object which works as an iterator.
-It will remain valid when other items are inserted or deleted, or even if
-the whole array is re-ordered. </p> <p>The insert and append methods leave
-the component on the Cleanup Stack using a dedicated Cleanup Item that protects
-the parent's array as well as the component itself. </p> <p>The insert and
-append methods allow each component to be given an ID. The ID must be unique
-only within the parent so typically a compound control will have an enum listing
-each of its children's IDs. <xref href="GUID-2D8BFBA2-79AC-364D-875D-E863CD4A2FE1.dita"><apiname>CCoeControlArray</apiname></xref> , accessed
-using <codeph>CCoeControl::Components()</codeph>, has a <codeph>ControlById()</codeph> method
-to retrieve components using their IDs. </p> <p>Components in the array are,
-by default, owned by the parent and will be deleted automatically when the
-parent is deleted. The default may be overridden using <codeph>CCoeControlArray::SetControlsOwnedExternally()</codeph>.
-The setting applies to all of the components. </p> <p>Controls may be removed
-from the array using one of the <codeph>Remove()</codeph> methods. These do
-not delete. </p> <codeblock id="GUID-9F9EC327-E7DE-59B8-838B-F5052E3750D3-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-15-10" xml:space="preserve">
-class CCoeControlArray
-        ...
-    public:
-        IMPORT_C TInt Remove(const CCoeControl* aControl);
-        IMPORT_C CCoeControl* Remove(TCursor aRemoveAt);
-        IMPORT_C CCoeControl* RemoveById(TInt aControlId);
-        ...
-</codeblock> <p>Using the component array as described is now the approved
-method of constructing and managing compound controls. In older versions of
-Symbian OS a specific method of handling components was not provided and developers
-were obliged to design their own. Bypassing the component array is still possible.
-It is necessary to allocate and store the components (typically as member
-data) and to implement the <codeph>CountComponentControls()</codeph> and <codeph>ComponentControl()</codeph> functions
-to return the number of components and a specified component to the framework.
-The new method offers significant advantages when controls are added and removed
-dynamically or are dependant on run-time data. The new method is also integrated
-with new layout managers. </p> </section>
-<section id="GUID-7E144310-9AF4-50F1-AD8A-9F9E05D554D1-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-16"><title>Size, position
-and layout</title> <p>There are several factors which contribute to a control's
-size and position. The control itself will require a certain size in order
-to display itself (and its data) correctly. The control's container will be
-responsible for positioning the control but is also likely to be responsible
-for positioning other controls - each of which will have its own requirements.
-Additionally there are the requirements of the UI's look and feel that must
-be complied with. </p> <p>Each control is responsible for implementing its
-own <codeph>Size()</codeph> function. </p> <p>Until Symbian OS version 9.1
-it was normal to write layout code for simple and compound controls in the <codeph>SizeChanged()</codeph> function.
-This is called by the framework, as one might expect, when a control's size
-(its 'extent') is changed. From 9.1, however, Symbian OS supports the use
-of the layout manager interface (<xref href="GUID-A622B8C7-60F4-38E8-B102-14883BCBA249.dita"><apiname>MCoeLayoutManager</apiname></xref>) and
-the <codeph>SizeChanged()</codeph> function is now implemented in the base
-class. (Note that if a control's position is changed, with no size change,
-using <codeph>CCoeControl::SetPosition()</codeph> its <codeph>PositionChanged()</codeph> function
-is called and that default implementation of <codeph>PositionChanged()</codeph> is
-empty). </p> <codeblock id="GUID-53A10820-550A-52C2-AE80-D556FD77E8FA-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-16-5" xml:space="preserve">
-class MCoeLayoutManager
-        ...
-    protected:
-        IMPORT_C MCoeLayoutManager();
-    
-    public:
-        virtual TBool CanAttach() const = 0;
-        virtual void AttachL(CCoeControl&amp; aCompoundControl) = 0;
-        virtual void Detach(CCoeControl&amp; aCompoundControl) = 0;
-        virtual TSize CalcMinimumSize(const CCoeControl&amp; aCompoundControl) const = 0;
-        virtual void PerformLayout() = 0;
-        virtual TInt CalcTextBaselineOffset(const CCoeControl&amp; aCompoundControl, const TSize&amp; aSize) const = 0;
-        virtual void SetTextBaselineSpacing(TInt aBaselineSpacing) = 0;
-        virtual TInt TextBaselineSpacing() const = 0;
-        virtual void HandleAddedControlL(const CCoeControl&amp; aCompoundControl, const CCoeControl&amp; aAddedControl) = 0;
-        virtual void HandleRemovedControl(const CCoeControl&amp; aCompoundControl, const CCoeControl&amp; aRemovedControl) = 0;
-        virtual TInt HandleControlReplaced(const CCoeControl&amp; aOldControl, const CCoeControl&amp; aNewControl) = 0;
-        ...
-</codeblock> <p>A layout manager may be attached to a compound control. </p> <codeblock id="GUID-ACCD143C-8618-5606-B749-D7EFE5C83ACD-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-16-7" xml:space="preserve">
-class CCoeControl
-        ...
-    protected: 
-        IMPORT_C MCoeLayoutManager* LayoutManager() const;
-        IMPORT_C virtual void SetLayoutManagerL(MCoeLayoutManager* aLayoutManager);
-
-    public:
-        IMPORT_C virtual TBool RequestRelayout(const CCoeControl* aChildCtrl);
-        ...</codeblock> <p>The default implementations of <codeph>MinimumSize()</codeph> and <codeph>SizeChanged()</codeph> now
-use the layout manager. </p> <codeblock id="GUID-88340A33-A58C-5856-AD47-C2E1637DD45F-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-16-9" xml:space="preserve">
-EXPORT_C TSize CCoeControl::MinimumSize()
-    { 
-    const MCoeLayoutManager* layoutManager = LayoutManager();
-    if (layoutManager)
-        return layoutManager-&gt;CalcMinimumSize(*this);
-    else    
-        return iSize;
-    }
-
-EXPORT_C void CCoeControl::SizeChanged()
-    {
-    MCoeLayoutManager* layout = LayoutManager();
-    if (layout)
-        layout-&gt;PerformLayout();
-</codeblock> <p>The layout manager is responsible for the size and position
-of the component controls. In practice it's likely that the UI variant libraries
-will provide concrete layout managers. Application developers should use these
-as the basis for control-specific layout managers. </p> </section>
-<section id="GUID-351911EE-87C7-5D11-8434-BA7FD3741745-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-17"><title> Drawing and
-refreshing</title> <p>A fundamental requirement of most controls is that they
-are able to render themselves onto the screen. For most controls the drawing
-process involves outputting text, painting backgrounds (either plain or from
-a bitmap), drawing shapes (graphics objects) and drawing component controls. </p> <p>Screen
-drawing may be initiated by the application itself, following something within
-the application changing, or by the Window Server, due to something else in
-the system updating the screen while the application is visible. In both cases
-the control's <codeph>Draw()</codeph> function will be called automatically
-by the framework. For compound controls all of the components' <codeph>Draw()</codeph> functions
-will also be called - unless the component lies completely outside the area
-that requires redrawing. </p> <p>As a control writer you will probably have
-to implement a <codeph>Draw()</codeph> function. </p> <p>Here is the signature
-for <codeph>Draw()</codeph>: </p> <codeblock id="GUID-7A83E8B5-9673-5EBC-B628-674734A07E0F-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-17-6" xml:space="preserve">private:
-    void Draw( const TRect&amp; aRect ) const ;</codeblock> <p>Note that it
-is private, takes a <codeph>const TRect&amp;</codeph> as a parameter, must
-not leave and is <codeph>const</codeph>. </p> <p>It should only be called
-by the framework. Application initiated redraws should be through calls to <codeph>DrawNow()</codeph>, <codeph>DrawDeferred()</codeph> or
-custom functions for drawing smaller elements. </p> <p>The <codeph>aRect</codeph> parameter
-is the part of the control that requires drawing (refreshing). </p> <p>The
-function is <codeph>const</codeph> and non-leaving because it is intended
-to support the decoupling of drawing actions from application state. </p> </section>
-<section id="GUID-FF7DB067-24AD-50C3-BF52-952F836609B0-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-18"><title>Drawing backgrounds</title> <p>A
-control's background is typically determined by the current colour scheme
-or skin. It may be a plain colour or a bitmap. It's also possible that a control
-is to appear non-rectangular or transparent in which case some of the background
-will be the control underneath. Prior to Symbian OS 9.1 controls were required
-to clear and update their whole area and creating these effects was rather
-complex. From 9.1 controls are drawn 'backmost first'. </p> <p>Background
-drawing should be done by a dedicated background drawer - i.e. an object which
-implements the <xref href="GUID-88936D48-B801-3D9C-8A9D-3498807937CE.dita"><apiname>MCoeControlBackground</apiname></xref> interface. A background
-can be attached to a <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita"><apiname>CCoeControl</apiname></xref> using <codeph>SetBackground()</codeph> and
-is used for that control and all of its children. When a control is drawn
-the framework looks for the nearest background up the run-time hierarchy and
-calls <codeph>MCoeControlBackground::Draw()</codeph>. </p> <p>UI variant libraries
-typically provide backgrounds. They are not owned by the controls to which
-they are attached. </p> </section>
-<section id="GUID-54C6A39A-CBD0-52E5-8CD0-76BE22247A54-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-19"><title>Drawing text</title> <p>Text
-must be drawn with the correct color, font, size and direction. As with backgrounds,
-these are determined at runtime according to UI customizations. This is achieved
-by means of a Text Drawer. Note the use of the <xref href="GUID-2280260C-3A4F-3C1E-ADF2-3219ED7FE0DE.dita"><apiname>XCoeTextDrawer</apiname></xref> class.
-This is a smart pointer (note the use of the <codeph>-&gt;</codeph> operator
-to access <xref href="GUID-C8C7B785-B3CF-3488-AEB1-BE0A70F6C1F2.dita"><apiname>CCoeTextDrawerBase</apiname></xref> functions) which ensures that
-only one text drawer is allocated on the heap at a time. </p> <codeblock id="GUID-511A9CEE-F02C-5667-A334-3C61A2428F0F-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-19-3" xml:space="preserve">
-XCoeTextDrawer textDrawer( TextDrawer() );
-textDrawer-&gt;SetAlignment(iAlignment); 
-textDrawer-&gt;SetMargins(iMargin);
-textDrawer-&gt;SetLineGapInPixels(iGapBetweenLines);
-textDrawer.SetClipRect(aRect); // have to use . [dot] operator for SetClipRect() as not CCoeTextDrawerBase function.
-
-textDrawer.DrawText(gc, *iTextToDraw, Rect(), *Font());
-</codeblock> <p>Text drawers are typically provided by the UI variant library
-or skin manager. Controls within the run-time hierarchy can set the text drawer
-for their children by overriding <codeph>GetTextDrawer()</codeph>. </p> <p>Note
-that the text drawer expects text to be passed as a <xref href="GUID-07D86324-ED54-3FCD-B301-53B7A6E04AE3.dita"><apiname>TBidiText</apiname></xref> rather
-than a descriptor. Controls should store all display text in <xref href="GUID-07D86324-ED54-3FCD-B301-53B7A6E04AE3.dita"><apiname>TBidiText</apiname></xref> objects.
-Application writers should consider the implications of right-to-left layouts
-for languages such as Hebrew and Arabic. </p> <p>A control's <codeph>GetTextDrawer()</codeph> function
-might look something like this. It checks on the current state of the control
-(<codeph>IsDimmed()</codeph>) and passes the call on to a skin manager. </p> <codeblock id="GUID-155AD8EC-17DD-5155-BE20-23246A33695C-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-19-7" xml:space="preserve">
-EXPORT_C void CMyButtonControl::GetTextDrawer(CCoeTextDrawerBase*&amp; aTextDrawer, const CCoeControl* aDrawingControl, TInt /*aKey*/) const
-    {
-    const TInt textDrawerIndex = (IsDimmed() ? EButtonTextDimmed : EButtonText);
-
-    SkinManager::GetTextDrawer(aTextDrawer, KSkinUidButton, textDrawerIndex, aDrawingControl);
-    }
-</codeblock> <p>If the control is drawing text on its own graphics (and does
-not care about the text drawer of its parents) it can just create an <xref href="GUID-2280260C-3A4F-3C1E-ADF2-3219ED7FE0DE.dita"><apiname>XCoeTextDrawer</apiname></xref> object
-on the stack in its <codeph>Draw()</codeph> method and initiate it from the
-skin that it is currently using to draw its graphics, using the <codeph>CSkinPatch::TextDrawer()</codeph> method,
-like this: </p> <codeblock id="GUID-3DFDBF27-8744-5283-AC7B-EC512EEEBB7D-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-19-9" xml:space="preserve">
-const CSkinPatch&amp; skin = SkinManager::SkinPatch(KSomeSkinUid, KSomeSkinIndex, this);
-
-skin.DrawBitmap(gc, Rect(), aRect);
-XCoeTextDrawer textDrawer( skin.TextDrawer(KSomeSkinUid, ESomeSkinTextDimmed, this) );
-
-const CFont&amp; font = ScreenFont(TCoeFont::NormalFont);
-textDrawer.DrawText(gc, iText, rect, font);
-</codeblock> <p>The example above also illustrates how to retrieve the correct
-font. <xref href="GUID-2A12FE3B-47F2-3016-8161-A971CA506491.dita"><apiname>CFont</apiname></xref> objects must not be stored in control member
-data as they must change when the control's zoom state changes. Instead, a <xref href="GUID-463C1928-878D-3B06-ABFD-178BE1BAD776.dita"><apiname>TCoeFont</apiname></xref> that
-represents a font's size (logical or absolute in pixels) and style (plain,
-bold, italic, subscript, or superscript) should be used. </p> <codeblock id="GUID-864A57DB-BCDA-50B6-B876-9EF62CFB27C6-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-19-11" xml:space="preserve">
-class TCoeFont 
-        ...
-    public: 
-        IMPORT_C TCoeFont(TLogicalSize aSize, TInt aStyle, TInt aFlags = ENoFlags); 
-        IMPORT_C TCoeFont(TInt aHeightInPixels, TInt aStyle, TInt aFlags = ENoFlags); 
-        IMPORT_C TCoeFont(const TCoeFont&amp; aFont);
-        IMPORT_C TCoeFont();
-        ...</codeblock> <p>By creating a <xref href="GUID-463C1928-878D-3B06-ABFD-178BE1BAD776.dita"><apiname>TCoeFont</apiname></xref> object
-describing the properties of the desired font, a <xref href="GUID-2A12FE3B-47F2-3016-8161-A971CA506491.dita"><apiname>CFont</apiname></xref> object
-reference (needed to actually draw the text) can be fetched from the <xref href="GUID-372CDE49-2148-3A21-8EA3-8D4656548C23.dita"><apiname>CCoeFontProvider</apiname></xref>.
-A font provider can be attached to any <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita"><apiname>CCoeControl</apiname></xref> and
-will keep information about the typeface used by that control and all controls
-below. A default font provider is attached to the <xref href="GUID-12A9389D-363B-3F54-857F-89EE0EDCDF40.dita"><apiname>CCoeEnv</apiname></xref>. </p> <codeblock id="GUID-C46BEB52-33DB-564B-9A64-53763C7CD226-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-19-13" xml:space="preserve">
-class CCoeControl
-        ...
-    public:
-        IMPORT_C const CCoeFontProvider&amp; FindFontProvider() const;
-        IMPORT_C void SetFontProviderL(const CCoeFontProvider&amp; aFontProvider);
-        ...
-        </codeblock> <p>To get hold of the <xref href="GUID-2A12FE3B-47F2-3016-8161-A971CA506491.dita"><apiname>CFont</apiname></xref> object
-a <codeph>Draw()</codeph> method can be implemented like this: </p> <codeblock id="GUID-45292362-1E39-59B0-AC7F-14C98592F059-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-19-15" xml:space="preserve">
-void CMyControl::Draw(const TRect&amp; aRect)
-    {
-    const CCoeFontProvider&amp; fontProvider = FindFontProvider();
-    const CFont&amp; font = fontProvider.Font(TCoeFont::LegendFont(), AccumulatedZoom());
-
-    XCoeTextDrawer textDrawer( TextDrawer() );
-    textDrawer-&gt;SetAlignment(EHCenterVCenter);
-    textDrawer.DrawText(gc, iText, rect, font);
-    }
-</codeblock> <p>For convenience there’s a <codeph>CCoeControl::ScreenFont()</codeph> method
-that locates the font provider and calls it with the control’s accumulated
-zoom: </p> <codeblock id="GUID-5974F900-84B7-5262-8428-88797911F94A-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-19-17" xml:space="preserve">
-class CCoeControl
-        ...
-    protected:
-        IMPORT_C const CFont&amp; ScreenFont(const TCoeFont&amp; aFont) const;
-        ...
-</codeblock> </section>
-<section id="GUID-D1AED2A8-94AC-54BB-9CEB-C8C3643AFBBD-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-20"><title>Drawing graphics</title><p>Controls
-draw graphics objects - lines, rectangles, shapes and bitmaps to a <keyword>graphics
-context</keyword>. The graphics context is provided by the Window Server and
-represents a group of settings appropriate for the physical device that is
-ultimately being drawn to. In most cases the device is a screen and a graphics
-context should be obtained using <codeph>CCoeControl::SystemGc()</codeph>. <codeph>CCoeControl::SystemGc()</codeph> gets
-the current graphics context from the run-time hierarchy. Controls in the
-hierarchy may override graphics context settings which will then be passed
-on to their children. <i>Controls should not get their graphics context directly
-from CCoeEnv as to do so would bypass the hierarchy</i>. </p> <codeblock id="GUID-DC2B7A84-BA93-5AE0-BABA-9CF6B156A54E-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-20-3" xml:space="preserve">
-void CMyControl::Draw( const TRect&amp; aRect )
-    {
-    CWindowGc&amp; gc = SystemGc() ; // get gc from run time hierarchy
-    TRect rect = TRect( Size() ) ;
-    if ( IsBlanked() )
-        {
-        // blank out the entire control
-        gc.SetPenStyle( CGraphicsContext::ENullPen ) ;
-        gc.SetBrushStyle( CGraphicsContext::ESolidBrush ) ;
-        TRgb blankColor = BlankingColor() ;
-        gc.SetBrushColor( blankColor ) ;
-        gc.DrawRect( rect ) ;
-        }
-    else
-        {
-        // draw masked bitmap in the centre of the control 
-        // The parent will draw the background 
-        TInt id = BitMapId() ;
-
-        TInt x = Size().iWidth - iBitmap[id]-&gt;SizeInPixels().iWidth ;
-        TInt y = Size().iHeight - iBitmap[id]-&gt;SizeInPixels().iHeight ;
-
-        TPoint pos = Rect().iTl ;
-        pos.iX = pos.iX + ( x / 2 ) ;
-        pos.iY = pos.iY + ( y / 2 ) ;
-
-        gc.BitBltMasked( pos, iBitmap[id], rect, iMaskBitmap, ETrue ) ;
-        }
-    }</codeblock> <p>Before a graphics context can be used it must be activated.
-After use it must be deactivated. Activation and deactivation are done automatically
-by the framework in <codeph>DrawNow()</codeph>, <codeph>DrawDeferred()</codeph> and <codeph>HandleRedrawEvent()</codeph> but
-must be done explicitly for any other application initiated drawing by calling <codeph>ActivateGc()</codeph> and <codeph>DeactivateGc()</codeph>. </p> <p>Controls may implement partial drawing to speed up performance. The <codeph>Draw()</codeph> function
-may be split into sub functions: <codeph>DrawThis()</codeph>, <codeph>DrawThat()</codeph>, <codeph>DrawTheOther()</codeph>.
-Each of these requires a corresponding <codeph>DrawThisNow()</codeph> and/or <codeph>DrawThisDeferred()</codeph> function. </p> <codeblock id="GUID-EDC0D6F1-61BC-552F-B56D-C32148ADECA3-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-20-6" xml:space="preserve">
-CMyControl::Draw()
-    {
-    DrawThis() ;
-    DrawThat() ;
-    DrawTheOther() ;
-    }</codeblock> <codeblock id="GUID-E026186D-7B55-5AB5-9391-8587E3510D6D-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-20-7" xml:space="preserve">
-CMyControl::DrawThisNow()
-    {
-    ActivateGc() ;
-    DrawThis() ;
-    DeactivateGc() ;
-    }</codeblock> </section>
-<section id="GUID-AC723EE4-1482-59C5-9F13-CAE119C7800D-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-21"><title>Handling events </title> <p>The
-Control Framework supports user interaction in two ways: key-press events
-and pointer events. Both types of event arrive through the Window Server though
-they each arrive in a slightly different way. Both are closely related to
-the concept of 'focus' and the location of the cursor. </p> <p><b>Handling
-key events </b> </p> <p>Key events are delivered to the AppUi. The Window
-Server channels them through the root window of its current window group which
-maps to the AppUi foreground application. The AppUi offers each key event
-to each of the controls on its control stack in priority order until one of
-the controls 'consumes' it. </p> <p>To receive key events a control must implement <codeph>CCoeControl::OfferKeyEventL()</codeph>.
-If it handles the event it must return <codeph>EKeyWasConsumed</codeph>: If
-it doesn't it must return <codeph>EKeyWasNotConsumed</codeph> so that the
-next control on the stack receives it. </p> <codeblock id="GUID-448E9DF8-9D63-5BA4-94A7-4FB4B96A6DEA-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-21-6" xml:space="preserve">
-TKeyResponse CMyControl::OfferKeyEventL( const TKeyEvent&amp; aKeyEvent, TEventCode aType)
-    {
-    TKeyResponse returnValue = EKeyWasConsumed ;
-    switch( aKeyEvent.iCode ) 
-        {
-        case EKeyEnter :
-            // do stuff
-            break ;
-        case EKeyEscape :
-            // do stuff :
-            break ;
-
-            ...
-                
-        default :
-            // did not recognise key event
-            returnValue = EKeyWasNotConsumed ;
-            break ;
-        }
-    return returnValue ;
-    }</codeblock> <p>The handling of key events will depend on the design
-and purpose of the control itself. Compound controls might need to keep track
-of an input <b>focus</b>, or <b>cursor</b>, and to pass key events amongst
-its lodgers. Input into one lodger might have an effect on another - pressing
-a navigation key might cause one control to lose the highlight and another
-to gain it, pressing a number key might cause a text editor to grow which
-might, in turn, require all of the components below it to shuffle downwards
-and a scroll bar to become visible (which might also require some controls
-to be laid out differently). </p> <p><b>Handling pointer events </b> </p> <p>Pointer
-events are slightly different as the position of the pointer, rather than
-of the focus, is significant. The Window Server passes a pointer event to
-the top-most visible window at the point of contact. The Framework uses the
-functions <codeph>ProcessPointerEventL()</codeph> and <codeph>HandlePointerEventL()</codeph> to
-work down the hierarchy. The Framework also uses the <xref href="GUID-A2BF9AE8-CF42-3D94-8763-66DB11EDDA46.dita"><apiname>MCoeControlObserver</apiname></xref> and
-focussing mechanisms to inform the observer of the controls that will be losing
-and gaining the focus. </p> <p><b>Using the Control Observer Interface</b></p><p>The
-Control Framework facilitates this type of relationship between a container
-and its lodgers with the <codeph>MCoeControlObserver</codeph> interface. Typically
-the container implements the interface and becomes the observer for each lodger
-that can receive user input (focus). There is only one function in <codeph>MCoeControlObserver</codeph>:</p><codeblock xml:space="preserve">virtual void HandleControlEventL( CCoeControl *aControl, TCoeEvent aEventType ) = 0 ;</codeblock><p>and it is called when an observed control calls</p><codeblock xml:space="preserve">void CCoeControl::ReportEvent( MCoeControlObserver::TCoeEvent aEvent ) ;</codeblock><p>A control can have only one observer (or none) so <codeph>ReportEvent()</codeph> does
-not need to specify an observer. An observer may observe any number of controls
-so <codeph>HandleControlEventL()</codeph> takes the observed control as a
-parameter. The other piece of information passed to the observer is a <codeph>TCoeEvent</codeph>.</p><codeblock xml:space="preserve">enum TCoeEvent
-    {
-    EEventRequestExit,
-    EEventRequestCancel,
-    EEventRequestFocus,
-    EEventPrepareFocusTransition,
-    EEventStateChanged,
-    EEventInteractionRefused
-	 };</codeblock><p><codeph>CCoeControl</codeph> also provides <codeph>IsFocused()</codeph>, <codeph>SetFocused()</codeph> and <codeph>IsNonFocussing()</codeph>. Note that Framework does not attempt to ensure exclusivity of focus, nor
-does it give any visible indication of focus. It is up to the application
-developer to ensure that only one control has the focus at a time, that the
-focus is correctly transferred between controls, that only appropriate controls
-receive the focus and that the focus is visible at all times.</p><codeblock xml:space="preserve">void CContainer::HandleControlEventL(CCoeControl* aControl, TCoeEvent aEventType)
-    {
-	 switch (aEventType)
-        {
-		   case EEventRequestFocus:
-			    {
-			    if( !(aControl-&gt;IsFocussed()) )
-				     {
-				     aControl-&gt;SetFocus( ETrue ) ;
-				     // remove focus from other controls
-				     for ( Tint ii = 0 ; ii &lt; CountComponentControls() ; ii++ ) 
-                     {
-					       CCoeControl* ctl = ComponentControl( ii ) ;
-					       if( ( ctl != aControl ) &amp;&amp; !( ctl-&gt;IsNonFocussing() ) )
-						        {
-						        aControl-&gt;SetFocus( EFalse ) ;
-						        }
-					       }
-				      }
-			     }
-			     break;
-	           ...
-		     }
-	    }</codeblock> <p>Control developers may implement <codeph>HandlePointerEventL()</codeph>,
-which is a virtual function, to perform pointer event functionality. The implementation
-must, however, call the base class function. </p> <p>Controls may modify their
-pointer area, possibly if they appear non-rectangular or overlap. To do so
-requires the addition of a hit test which describes a hit-test region. A hit-test
-region may cover all or part of one or more controls. A hit for a control
-is registered in the area covered by both the control and its associated hit
-test. </p> <p>The diagram below represents three controls, each of which is
-rectangular but which appears on the screen as a non-rectangular bitmap. Only
-a hit on a bitmap area should register. This could be achieved by defining
-a single hit-test region in the shape (and position) of the three blue areas
-and associating it with each of the controls. The class that implements the
-hit-test region must implement the MCoeControlHitTest interface. </p> <fig id="GUID-5C856964-8553-543A-B7E2-8D5DCA9BF52C-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-21-22">
-<title>              Hit-test region example            </title>
-<image href="GUID-CF34E1C9-48E5-5B91-A48E-C68E647116A0_d0e53527_href.png" placement="inline"/>
-</fig> <codeblock id="GUID-D2AF9CEB-3072-5239-A157-D19852076CEF-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-21-23" xml:space="preserve">
-class MCoeControlHitTest
-        ...
-    public:
-        virtual TBool HitRegionContains( const TPoint&amp; aPoint, const CCoeControl&amp; aControl ) const = 0;
-</codeblock> <p>A hit test is associated with a control using <codeph>CCoeControl::SetHitText()</codeph>.
-The base class implementation of <codeph>HandlePointerEventL()</codeph> performs
-the following test: </p> <codeblock id="GUID-35C26C5B-A19A-528A-B5BE-B8177F81B05D-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-21-25" xml:space="preserve">
-    ...
-    const MCoeControlHitTest* hitTest = ctrl-&gt;HitTest() ;
-    if( hitTest )
-        {
-        if( hitTest-&gt;HitRegionContains( aPointerEvent.iPosition, *ctrl ) &amp;&amp;
-                        ctrl-&gt;Rect().Contains( aPointerEvent.iPosition ) )</codeblock> <p>Note
-that this is performed by a container when deciding which lodger to pass the
-event onto. This snippet also illustrates how a control can find where (<codeph>iPosition</codeph>)
-the pointer event actually occurred. </p> <p>Pointer support includes dragging
-&amp; grabbing. See <xref href="GUID-1FFA0073-3D83-388E-A824-08C31F90CC54.dita"><apiname>TPointerEvent</apiname></xref>. </p> </section>
-<section id="GUID-FE221E89-1817-5A73-8FBA-212FBC030766-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-22"><title>Implementing
-the Object Provider (MOP) interface</title> <p>The <xref href="GUID-F32E2F00-B68F-59B2-AABA-181E16354C86-GENID-1-8-1-3-1-1-7-1-7-1-9-1.dita">Object
-Provider mechanism</xref> exists to allow a control to call a function on
-another control in the hierarchy for which it does not have a reference. It
-simply calls <codeph>MopGetObject()</codeph> specifying the interface containing
-the function. It may also call <codeph>MopGetObjectNoChaining()</codeph> to
-inquire of a specific object whether it supports the requested interface. </p> <p>Only
-controls which wish to supply an interface require customisation. In order
-to be identifiable an interface must have an associated UID. The following
-code samples show how <xref href="GUID-0DC77F9B-718A-31DF-B076-3C3F83378BF4.dita"><apiname>CEikAlignedControl</apiname></xref> implements and
-supplies <xref href="GUID-65610725-E873-3F8D-AD60-FC0AD726E0C5.dita"><apiname>MEikAlignedControl</apiname></xref>: </p> <codeblock id="GUID-9926598F-163B-5ACF-B320-66B43D331E1A-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-22-4" xml:space="preserve">
-class MEikAlignedControl
-        ...
-    public:
-        DECLARE_TYPE_ID( 0x10A3D51B )  // Symbian allocated UID identifies this interface
-        ...
-</codeblock> <codeblock id="GUID-1C2FE28B-7A1F-5726-8690-50FBA8672A2C-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-22-5" xml:space="preserve">
-class CEikAlignedControl : public CCoeControl, public MEikAlignedControl
-    {
-        ...
-    private: //from CCoeControl
-        IMPORT_C TTypeUid::Ptr MopSupplyObject( TTypeUid aId ) ;
-        ...
-</codeblock> <codeblock id="GUID-03CD8613-9C1D-556C-94B7-5D9A1C23FF83-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-22-6" xml:space="preserve">
-EXPORT_C TTypeUid::Ptr CEikAlignedControl::MopSupplyObject( TTypeUid aId )
-    {
-    if( aId.iUid == MEikAlignedControl::ETypeId )
-        return aId.MakePtr( static_cast&lt;MEikAlignedControl*&gt;( this ) ) ;
-
-    return CCoeControl::MopSupplyObject( aId ) ; // must call base class!
-    }
-</codeblock> <p>To get an interface from the object provider framework the
-caller must use a pointer to the interface. </p> <codeblock id="GUID-CB641ADD-5AFE-5D72-A909-CD3F0C3BAA9A-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-22-8" xml:space="preserve">
-    ...
-    MEikAlignedControl* alignedControl = NULL ;
-    MyControl-&gt;MopGetObject( alignedControl ) ;
-    if ( alignedControl )
-        {
-        ... // etc.</codeblock> <p>To get an interface from a specific object
-the caller may use the no-chaining function call. </p> <codeblock id="GUID-AEB5EB12-6289-5DCB-BF07-71B8F7A67E33-GENID-1-8-1-6-1-1-4-1-6-1-9-1-2-22-10" xml:space="preserve">
-    ...
-    MEikAlignedControl* alignedControl = NULL ;
-    aControl-&gt;MopGetObjectNoChaining( alignedControl ) ;
-    if ( alignedControl )
-        {
-        ... // etc.</codeblock> </section>
-</conbody></concept>
\ No newline at end of file