UIQ Technology
Symbian OS Library

UIQ 3.1 SDK        UIQ developer portal

[Index] [Spacer] [Previous] [Next]



UIQ Controls - Plain Text Editor


1. Introduction

This guide explains the UIQ control Plain Text Editor also called Edwin (CEikEdwin). The Plain Text Editor allows users to view, enter and edit plain texts, that is, characters without formatting. The class CEikEdwin defines and implements the Plain Text Editor.

The following settings are available to be used by the application developer during the creation phase of the control exclusively:

The following operations can be performed at any time:

By default, the following configuration applies:

Some of the features can be seen in this table.

Control snapshot Description

Read-only text.

Possible to add and change the text.

Wrapping of text is active.

Single line editor.

Multi-line editor.

Part of text is selected.

Editor is dimmed.

Scroll bar is active.

A specific border is used.


1.1 Further Reference

See the API documentation for Plain Text Editor CEikEdwin.

Global Text Editor and Rich Text Editor are more sophisticated editors. Global Text Editor supports formatting characters and paragraphs for the whole text. Rich Text Editor supports formatting of individual characters and paragraphs within the text.

Global Text Editor is derived from Plain Text Editor. Rich Text Editor is derived from Global Text Editor. See the How To guide for Rich Text Editor.

See even the API documentation for Global Text Editor (CEikGlobalTextEditor) and Rich Text Editor (CEikRichTextEditor).

[Top]


2. Architecture

There is no need to know about any other class to be able to use Plain Text Editor.

High-level architecture of the Plain Tex...

High-level architecture of the Plain Text Editor

[Top]


3. Using the Control

This section explains how Plain Text Editor is constructed, used and destroyed. Source code examples are used and explained to illustrate how the control is used.


3.1 Includes and Identifications

Use the following #include directive:

#include <eikedwin.h>

Use the following LIBRARY directive in the project's mmp-file:

LIBRARY eikcoctl.lib    

Use the following control identifier when specifying the control in resource data files. It is used by the framework when constructing the control from resource data:

EEikCtEdwin 


3.2 Resource Structure

Resource files can be used to create the control. The resource to use is defined by the EDWIN structure, defined in uikon.rh. The structure looks like this:

STRUCT EDWIN
    {
    LONG flags=0;
    WORD width=0;
    WORD lines=1;
    WORD maxlength=0;
    }

The values given in the structure definition are default values. The structure contains the following:

Resource flags Flag description

EEikEdwinKeepDocument

If set, the Plain Text Editor does not destroy its content on destruction.

EEikEdwinSegmentedStorage

If set, the content buffer uses segmented storage.

EEikEdwinWidthInPixels

If set, the width specified in resource is given in pixels, not in characters. This is used when constructing the object.

EEikEdwinNoAutoSelection

If set, no automatic selection of the entire text is made when Plain Text Editor gets focus. This is the default behavior.

EEikEdwinJustAutoCurEnd

If set, the cursor is moved to the end of the text whenever the control is activated. This is the default behavior.

EEikEdwinNoWrap

If set, the text being edited will not wrap.

EEikEdwinLineCursor

If set, a line cursor will be used instead of a block cursor.

EEikEdwinNoHorizScrolling

If set, horizontal scrolling is disabled.

EEikEdwinInclusiveSizeFixed

If set, scroll bars required to edit long documents appear inside the Plain Text Editor. This reduces the area used to display text. If not set, scroll bars appear outside the Plain Text Editor.

EEikEdwinUserSuppliedText

If set, the height of the Plain Text Editor is set according to the number of lines of text supplied by the user.

EEikEdwinOwnsWindow

If set, the Plain Text Editor is a window-owning control.

EEikEdwinDisplayOnly

If set, the Plain Text Editor does not respond to input at all.

EEikEdwinAlwaysShowSelection

If set, the selection will not be hidden if the Plain Text Editor loses focus.

EEikEdwinReadOnly

If set, the Plain Text Editor is read-only and the user cannot add text to any document it displays. If attempts are made to add texts to a read-only Plain Text Editor, a message will be displayed informing about the read-only state.

EEikEdwinAllowPictures

If set, no special attempt to delete embedded pictures cleanly will be made. This flag does not apply to Plain Text Editor which does not edit rich text.

EEikEdwinAllowUndo

If set, the Plain Text Editor supports undo operations.

EEikEdwinNoLineOrParaBreaks

If set, no line or paragraph breaks are allowed in the text being edited.

EEikEdwinOnlyASCIIChars

If set, only ASCII characters are allowed.

EEikEdwinResizable

If set, the Plain Text Editor is resizable.

EEikEdwinIgnoreVirtualCursor

If set, the Plain Text Editor ignores the virtual cursor.

EEikEdwinNoCustomDraw

For internal use.

EEikEdwinCustomWrap

For internal use.

EEikEdwinNoTextParsers

If set, the document will not be parsed for embedded objects.

EEikEdwinNoCursorWrap

If set, cursor wrapping is disabled. Cursor wrapping is when the cursor position is at the bottom or top of the document and it jumps to the other end of the document when the appropriate navigation key is pressed.

EEikEdwinEnableAutoSelection

If set, automatic selection of the entire text when the Plain Text Editor gets focus is enabled.

This flag works together with the EEikEdwinNoAutoSelection flag. If neither flag is set or if both flags are set, the EEikEdwinNoAutoSelection flag, and only the EEikEdwinNoAutoSelection flag, will be set since this is the default behavior.

EEikEdwinDisableAutoCurEnd

If set, automatic repositioning of the cursor to the end of the text when the control is activated is disabled.

This flag works together with the EEikEdwinJustAutoCurEnd flag. If neither flag is set or if both flags are set, the EEikEdwinJustAutoCurEnd flag, and only the EEikEdwinJustAutoCurEnd flag, will be set since this is the default behavior.

EEikEdwinNoCursorWrapUp

If set, cursor wrapping from the top to the bottom of the document is disabled.


3.3 Construction

This section discusses four different ways of constructing controls. The first three ways describe how to construct and add a control to the view of an application. The view framework is used in all three cases but in three different ways. The fourth way describes how to construct and launch a dialog from an application. The dialog framework constructs the control and adds it into the dialog.

A common way to construct controls is to specify them in resource files and let the framework construct them from there. Specifying the controls in resource files is the preferred way of constructing controls, since it allows for easier modifications compared to creating them entirely from source code.

This section covers different ways of constructing the control.

3.3.1 Construction with View Framework Using Data from a Resource File

The example below describes how to construct the control using the view framework.

The reason the example seems to be rather complex is because it demonstrates how to construct a complete view containing a Scrollable Container and a Layout Manager. It also encapsulates the control in a Building Block. The view supports both pen and softkey styles; support of both styles in a view is optional.

1) Declare an enumeration for the controls to be used in the view in a *.hrh file. Hrh files are files to be included both in resource files (*.rss) and C++ files.

/* Declare the controls' Id in a *.hrh file for use both in resource and cpp */
enum TMyViewControls
    {
    EMyViewEdwin,
    EMyViewScrollableContainer,
    EMyViewBuildingBlock,
    EMyViewNumberOfControls
    };

2) Declare the controls to be used in the view in your resource (*.rss) file:

/* Declare the set of controls to be used in the View */
RESOURCE QIK_CONTROL_COLLECTION r_my_edwin_view_controls
    {
    items =
        {
        QIK_CONTROL
            {
            unique_handle = EMyViewScrollableContainer;
            type = EQikCtScrollableContainer;
            control = r_my_edwin_scroll_pane;
            },
        QIK_CONTROL
            {
            unique_handle = EMyViewBuildingBlock;
            type = EQikCtCaptionedTwolineBuildingBlock;
            control = r_my_edwin_building_block;
            },
        QIK_CONTROL
            {
            unique_handle = EMyViewEdwin;
            type = EEikCtEdwin;
            control = r_my_edwin;
            }
        };
    }

3) Define the view and its contents in your resource file:

/* The view */
RESOURCE QIK_VIEW r_my_edwin_view
    {
    pages = r_my_edwin_viewpages;
    }
                
/* The view page */
RESOURCE QIK_VIEW_PAGES r_my_edwin_viewpages
    {
    pages =
        {
        QIK_VIEW_PAGE
            {
            container_unique_handle = EMyViewScrollableContainer;
            page_content = r_my_edwin_view_container_details;
            }           
        };
    }

4) Define the resource for the Scrollable Container used in the view:

/* The scrollable container used in the view */
RESOURCE QIK_SCROLLABLE_CONTAINER r_my_edwin_scroll_pane
    {
    }

5) Declare the contents and properties for the Scrollable Container used in the view:

/* Contents of the scrollable container used in the view */
RESOURCE QIK_SCROLLABLE_CONTAINER_SETTINGS r_my_edwin_view_container_details
{
    controls =
        {
        QIK_CONTAINER_ITEM
            {
            unique_handle = EMyViewBuildingBlock;
            }
        };
    }

6) Define the control resource structure used in the view:

/* The Edwin used in the view */
RESOURCE EDWIN r_my_edwin
    {
    flags = 0;
    width = 10;
    lines = 1;
    maxlength = 20;
    }

7) Define the settings for the Building Block containing the control:

/* Settings for the EQikCtCaptionedTwolineBuildingBlock containing the edwin */ 
RESOURCE QIK_SYSTEM_BUILDING_BLOCK r_my_edwin_building_block
    {
    content =
        {
        QIK_SLOT_CONTENT
            {
            slot_id = EQikItemSlot1;
            caption = "Choose:";
            },
        QIK_SLOT_CONTENT
            {
            slot_id = EQikItemSlot2;
            unique_handle = EMyViewEdwin;
            }
        };
    }

8) The configurations of the view:

RESOURCE QIK_VIEW_CONFIGURATIONS r_my_edwin_ui_configurations
    {
    configurations=
        {
        QIK_VIEW_CONFIGURATION
            {
            ui_config_mode = KQikSoftkeyStylePortrait;
            view = r_my_edwin_view;
            command_list = r_my_edwin_commands;
            },
        QIK_VIEW_CONFIGURATION
            {
            ui_config_mode = KQikPenStyleTouchPortrait;
            view = r_my_edwin_view;
            command_list = r_my_edwin_commands;
            }
            }
        };
    }

9) The command list for the view:

RESOURCE QIK_COMMAND_LIST r_my_edwin_commands
    {
    items =
        {
        // This command shall only be visible in debug mode because it is only
        // used to find memory leaks during development of the application.
        QIK_COMMAND
            {
            id = EEikCmdExit;
            type = EQikCommandTypeScreen;
            // Indicate that this command will only be visible in debug
            stateFlags = EQikCmdFlagDebugOnly;
            text = "Close (debug)";
            }
        };
    }

10) The view framework constructs the view described in this example with this code:

#include <eikedwin.h>
                    
void CMyView::ViewConstructL()
    {
    ViewConstructFromResourceL(R_MY_EDWIN_UI_CONFIGURATIONS, R_MY_EDWIN_VIEW_CONTROLS);
                        
    // Get a pointer to the editor and initialize it with a text.
    CEikEdwin* edwin = LocateControlByUniqueHandle<CEikEdwin>(EMyViewEdwin);

    _LIT(KEdwin, "Plain Text Editor");
                    
    if(edwin)
        edwin->SetTextL(&KEdwin);
    }

11) The result should look something like this:

Result of creating the Plain Text Editor...

Result of creating the Plain Text Editor, in a Building Block, from resource using the view framework

3.3.2 Construction with Your Own C++ Code Using Data from a Resource File

The example below describes how to construct the control from resource with your own C++ code.

The reason the example seems to be rather complex is because it demonstrates how to construct a complete view containing a Scrollable Container and a Layout Manager. It also encapsulates the control in a Building Block.

This example uses the resource structures from the previous example. The following code creates the control:

#include <QikBuildingBlock.h>
#include <QikRowLayoutManager.h>
#include <QikGridLayoutManager.h>
#include <eikedwin.h>
                    
void CMyView::ViewConstructL()
    {
                    
    // Create a layout manager to be used inside the view
    CQikGridLayoutManager* gl = CQikGridLayoutManager::NewLC();
    SetLayoutManagerL(gl);
    CleanupStack::Pop(gl);
                        
    // Create a container and add it to the view
    ControlProvider()->ControlInfos().AddFromResourceL(R_MY_EDWIN_VIEW_CONTROLS);
    CQikContainerBase* container = static_cast<CQikContainerBase*>(ControlProvider()->ControlConstructIfNeededL(EMyViewScrollableContainer, *this));
    ASSERT(container);
    Controls().AppendLC(container);
    CleanupStack::Pop(container);
                        
    // Create a layout manager to be used inside the container
    CQikRowLayoutManager* rowlayout = CQikRowLayoutManager::NewLC();
    container->SetLayoutManagerL(rowlayout);
    CleanupStack::Pop(rowlayout);
                        
    // Create the Building Block (containing the control) and add it to the Container
    CQikBuildingBlock* block = CQikBuildingBlock::CreateSystemBuildingBlockL(EQikCtCaptionedTwolineBuildingBlock);
    container->AddControlLC(block, EMyViewBuildingBlock);
    TResourceReader blockReader;
    iCoeEnv->CreateResourceReaderLC(blockReader,R_MY_EDWIN_BUILDING_BLOCK);
    block->ConstructFromResourceL(blockReader, *ControlProvider());
    CleanupStack::PopAndDestroy(); //blockReader
    CleanupStack::Pop(block);
    }

What the code does

1) Initializes a Command Manager with an empty Command List. The controls placed in the view add their commands to the Command List when they receive focus.

2) Creates a Layout Manager for the view. The Grid Layout Manager fills the view with its only control in this example, the Scrollable Container.

3) Loads the control collection R_MY_VIEW_CONTROLS into the Control Provider. Then the Control Provider is asked to create the Scrollable Container.

4) Uses the MopGetObjectNoChaining function to determine that the control that was created really is a class of the type CQikContainerBase before it is added to the view.

5) Creates a Layout Manager to control the layout inside the container. Adds the Layout Manager to the container.

6) Constructs a Building Block containing the control from the resource R_MY_BUILDING_BLOCK. Adds the Building Block to the container.

The control can also be created without a Building Block. In that case, replace the last section in the code above, from the "Create building block..." comment, with the following code.

Since a pointer to the control is declared here, eikedwin.h needs to be included in the cpp-file and eikcoctl.lib in the mmp-file.

// Create the control and add it to the container
TResourceReader reader;
iEikonEnv->CreateResourceReaderLC(reader, R_MY_EDWIN);
CEikEdwin* edwin = new (ELeave) CEikEdwin();
container->AddControlLC(edwin, EMyViewEdwin);
edwin->ConstructFromResourceL(reader);   
edwin->SetUniqueHandle(EMyViewEdwin);
CleanupStack::Pop(edwin);
CleanupStack::PopAndDestroy(); //reader

Use AddControlLC to add controls to a Scrollable Container. Add the controls as soon as they are created. Do not push them onto the Cleanup Stack before they are added. Do not pop them from the Cleanup Stack until they are fully constructed. A TCleanupItem created in AddControlLC will make sure that the control is both cleaned up and removed from the Components Array if a leave occurs before the control is fully constructed.

7) The result should look something like this:

Result of creating the Plain Text Editor...

Result of creating the Plain Text Editor, not in a Building Block, from resource using C++ code

3.3.3 Construction Solely from C++ Code

The example below describes how to construct the control solely from C++ code.

The reason the example seems to be rather complex is because it demonstrates how to construct a complete view containing a Scrollable Container and a Layout Manager.

The following source code constructs the control:

#include <QikScrollableContainer.h>
#include <QikRowLayoutManager.h>
#include <QikGridLayoutManager.h>
#include <QikBuildingBlock.h>
#include <eikedwin.h>

void CMySinglePageView::ViewConstructL()
    {
    // Give a Layout Manager to the view
    CQikGridLayoutManager* gridlayout = CQikGridLayoutManager::NewLC();
    SetLayoutManagerL(gridlayout);
    CleanupStack::Pop(gridlayout);
                        
    // Create a container and add it to the view
    CQikScrollableContainer* container = new (ELeave) CQikScrollableContainer();
    Controls().AppendLC(container);
    container->ConstructL(EFalse);
    CleanupStack::Pop(container);
                        
    // Create a Layout Manager to be used inside the container
    CQikRowLayoutManager* rowlayout = CQikRowLayoutManager::NewLC();
    container->SetLayoutManagerL(rowlayout);
    CleanupStack::Pop(rowlayout);
                    
    // Create the control and add it to the container
    CEikEdwin* edwin = new (ELeave) CEikEdwin();
    container->AddControlLC(edwin, EMyViewEdwin);
    _LIT(KEdwinText, "Plain Text Editor");
    edwin->ConstructL(0, 10, 20, 1);
    edwin->SetUniqueHandle(EMyViewEdwin);
    edwin->SetObserver(this);
    edwin->SetTextL(&KEdwinText);
    CleanupStack::Pop(edwin);
    }

What the code does

1) Initializes the Command Manager with an empty Command List. The controls placed in the view add their commands to the Command List when they receive focus.

2) Creates a Layout Manager for the view. The Grid Layout Manager fills the view with its only control in this example, the Scrollable Container.

3) Instantiates a container and adds it to the view.

4) Creates a Layout Manager and adds it to the container.

5) Creates the control from C++ code. Sets the view, this, to be an observer of the control. The view's base class, CQikViewBase, handles focus changes in its method HandleControlEventL. For more details see the section below on how to be notified with Control Events.

3.3.4 Construction with the Dialog Framework Using Data from a Resource File

The control can be constructed from resource files in dialogs as well. To construct a dialog from resource a valid resource definition of that dialog must be in one of the project's resource files.

An example of a dialog resource containing the control is given below. For more information about the dialog class and its resource structure see CEikDialog and DIALOG in the API documentation.

1) Declare a dialog resource containing the control:

RESOURCE DIALOG r_my_edwin_dialog
    {
    title = "Test of control in dialog";
    flags = EEikDialogFlagWait;
    items =
        {
        DLG_LINE
            {
            prompt = "Edwin:";
            type = EEikCtEdwin;
            control = EDWIN
                {
                flags = 0;
                width = 10;
                lines = 1;
                maxlength = 30;
                };
            }
        };
    }

The resource properties inside the control block are the same as the ones described in the previous section.

2) Launch the dialog using the following source code. The dialog resource ID is passed as an argument:

#include <eikdialg.h>

CEikDialog* dlg = new (ELeave) CEikDialog();
dlg->ExecuteLD(R_MY_EDWIN_DIALOG);

The function returns immediately if EEikDialogFlagWait has not been specified in the dialog resource. If EEikDialogFlagWait is specified, it returns when the dialog exits. The dialog framework will in both situations delete the dialog appropriately as indicated by the D suffix of the ExcecuteLD function name.

3) The result should look something like this:

Result of creating the Plain Text Editor...

Result of creating the Plain Text Editor from a dialog resource


3.4 Using the Plain Text Editor

This section covers the most common functions used for interacting with the control.

When constructing the control with resource data, no reference to the control is available in the view class. When constructing the control with code, the preferred way might be to not save a reference to the control. In both these cases, the LocateControlByUniqueHandle function is used to get a pointer to the control by supplying the control's unique handle. When constructing the view and the control from code, you must explicitly set this unique handle by calling the method SetUniqueHandle. See the code examples below.

Note that the function will return NULL if the control could not be found. Always check the pointer before using it!

// Set the unique handle
edwin->SetUniqueHandle(EMyViewEdwin);

// Get a pointer to the control
CEikEdwin* edwin = LocateControlByUniqueHandle<CEikEdwin>(EMyViewEdwin);

3.4.1 Get Edited Text

Get the edited text in the control by using the following code:

HBufC* name = edwin->GetTextInHBufL();

You can also call the GetText() function to get the edited text in the control. But in this case you must provide a descriptor large enough to hold the text:

TBuf<LARGE_ENOUGH_NUMBER> buf;
edwin->GetText(buf);

3.4.2 How to be Notified with Control Events

In order to be notified when the control changes state you must add an observer to the control. An observer is an object of the type MCoeControlObserver. The Observer will then receive a function call to its function HandleControlEventL(CCoeControl* aControl, TCoeEvent aEventType) when the control changes state.

The view base class, CQikViewBase, implements the MCoeControlObserver. The HandleControlEventL function must be overloaded in the view class, because the view inherits from CQikViewBase.

The following source code example shows how to add an object as an observer and how to receive events from the control:

void CMyView::ViewConstructL()
    {
    // Construction code
    …

    // Adding this object as an observer
    edwin->SetObserver(this);
    }

void CMyView::HandleControlEventL(CCoeControl* aControl, TCoeEvent aEventType)
    {
    // Call base class to get focus navigation right
    CQikViewBase::HandleControlEventL(aControl, aEventType);

    CEikEdwin* edwin = LocateControlByUniqueHandle<CEikEdwin>(EMyViewEdwin);

    if(aControl == edwin)
        {
        switch(aEventType)
            {
            case EEventStateChanged:
                // The internal state of the control was changed. User interacted with the control.
                break;
                                    
            case EEventRequestExit:
                break;
                                    
            case EEventRequestCancel:
                break;
                                    
            case EEventRequestFocus:
                // The control received a pointer down event
                break;
                                    
            case EEventPrepareFocusTransition:
                // A focus change is about to appear
                break;
                                
            case EEventInteractionRefused:
                // The control is dimmed and received a
                // pointer down event.
                break;
                                
            default:
                break;
            }
        }
    }

The reason for calling the base class's HandleControlEventL function is that the view base class, CQikViewBase, handles focus management between controls in the view. If the control's observer is not a class which derives from CQikViewBase, focus management must be resolved by the observer itself. If a control requests focus and does not get it from the observer, it will generate a panic in some cases if the observer does not leave.

For more details on the TCoeEvent type, see class MCoeControlObserver in the API documentation.

3.4.3 How to be Notified with Edwin Events

To be notified when changes occur to the Plain Text Editor content or cursor position, an observer must be added to the control. The observer is an object of the type MEikEdwinObserver. The observer receives a function call to its function HandleEdwinEventL when these changes occur to the control. The following source code example shows how to add an object as an observer and how to receive these events from the control:

EEventFormatChanged - Sent when the formatting of the content of the Plain Text Editor changes.

EEventNavigation - Sent when cursor position changes.

void CMyView::ViewConstructL()
    {
    // Construction code
    …

    // Adding this object as an observer
    edwin->SetEdwinObserver(this);
    }

void CMyView::HandleEdwinEventL(CEikEdwin* aEdwin, TEdwinEvent aEventType)
    {
    CEikEdwin* edwin = LocateControlByUniqueHandle<CEikEdwin>(EMyViewEdwin);

    if(aControl == edwin)
        {
        switch(aEventType)
            {
            case EEventFormatChanged:
                break;
                                    
            case EEventNavigation:
                break;
                                                                    
            default:
                break;
            }
        }
    }

3.4.4 How to be Notified with Plain Text Editor Size Events

To be notified when changes occur to the size of the Plain Text Editor an observer must be added to the control. The observer is an object of the type MEikEdwinSizeObserver. The observer receives a function call to its function HandleEdwinSizeEventL when this change occurs to the control. When the Plain Text Editor's observer receives an event of this type, it handles it by making its view larger or smaller according to the new size. The following source code example shows how to add an object as an observer and how to receive these events from the control:

EEventSizeChanging - Sent when the size of the Edwin control changes.

void CMyView::ViewConstructL()
    {
    // Construction code
    …

    // Adding this object as an observer
    edwin->SetEdwinSizeObserver(this);
    }

TBool CMyView::HandleEdwinSizeEventL(CEikEdwin* aEdwin, TEdwinSizeEvent aEventType, TSize aDesirableEdwinSize)
    {                   
    CEikEdwin* edwin = LocateControlByUniqueHandle<CEikEdwin>(EMyViewEdwin);

    if(aControl == edwin)
        {
        switch(aEventType)
            {
            case EEventSizeChanging:
                break;
                                    
            default:
                break;
            }
        }
    }

3.5 Destruction

Destroying the control is just a matter of invoking operator delete on the control object. Just keep in mind whether the control deletes its document or not. This is indicated by the EEikEdwinKeepDocument flag. If the control does not delete its document, someone else must take care of that.


4. Subclassing

Subclassing Plain Text Editor is not recommended.