Using Field Visualizations

Visual Lansa’s field visualization capabilities are very powerful. I have come across many areas in code where the visual display of data is manipulated in code within forms and reusable parts…only to be duplicated in other forms and reusable parts. Inevitably, this leads to bugs as different areas of an application behave differently (never mind the terrible inefficiency). In Lansa you can create a reusable part to act as a visual class for a field or multiple fields. In the example below, the original form contained code to display a field “prompt” to indicate the data required without taking up space with a label. The amount of code just to manage the prompt text was extraneous and redundant. This was refactored into a single reusable part and added to each fields visualization as defined below. One could easily take this code a step further and add formatting and validation routines for common data types like currency, phone numbers, email addresses, etc. If you are writing Visual Lansa applications in RDMLX and are not using field visualizations I would highly recommend looking into their use!

Screenshot

Field Visualization Reusable Part Code:

FUNCTION OPTIONS(*DIRECT)
BEGIN_COM ROLE(*EXTENDS #PRIM_PANL) DEFAULTPTY(Value) DISPLAYPOSITION(1) HEIGHT(18) LAYOUTMANAGER(#ATLM_1) LEFT(0) TABPOSITION(1) TABSTOP(False) TOP(0) WIDTH(200)

* =======================================================
* Component Definitions
* =======================================================
DEFINE_COM CLASS(#PRIM_ALPH) NAME(#PasswordChar)
DEFINE_COM CLASS(#PRIM_BOLN) NAME(#RequiredField)
DEFINE_COM CLASS(#PRIM_EDIT) NAME(#EditBox) DISPLAYPOSITION(1) HEIGHT(18) LEFT(0) PARENT(#COM_OWNER) SHOWSELECTION(False) SHOWSELECTIONHILIGHT(False) TABPOSITION(1) TOP(0) WIDTH(200)
DEFINE_COM CLASS(#PRIM_ATLI) NAME(#ATLI_1) ATTACHMENT(Center) MANAGE(#EditBox) PARENT(#ATLM_1)
DEFINE_COM CLASS(#PRIM_ATLM) NAME(#ATLM_1)

* =======================================================
* Field Definitions
* =======================================================
DEFINE FIELD(#wNme) TYPE(*CHAR) LENGTH(10)
DEFINE FIELD(#wRet) TYPE(*CHAR) LENGTH(2)
DEFINE FIELD(#wTyp) TYPE(*CHAR) LENGTH(1)
DEFINE FIELD(#wLen) TYPE(*DEC) LENGTH(15) DECIMALS(0)
DEFINE FIELD(#wDec) TYPE(*DEC) LENGTH(15) DECIMALS(0)
DEFINE FIELD(#wChr) TYPE(*DEC) LENGTH(15) DECIMALS(0)
DEFINE FIELD(#wRef) TYPE(*CHAR) LENGTH(10)
DEFINE FIELD(#wDsc) TYPE(*CHAR) LENGTH(40)
DEFINE FIELD(#wLbl) TYPE(*CHAR) LENGTH(15)
DEFINE FIELD(#wHdg) TYPE(*CHAR) LENGTH(60)
DEFINE FIELD(#wOut) TYPE(*CHAR) LENGTH(40)
DEFINE FIELD(#wInp) TYPE(*CHAR) LENGTH(40)

* =======================================================
* Property Definitions
* =======================================================
DEFINE_PTY NAME(Value) GET(GetValue) SET(SetValue)
DEFINE_PTY NAME(ReadOnly) GET(GetReadOnly) SET(SetReadOnly)
DEFINE_PTY NAME(ShowError) GET(GetShowError) SET(SetShowError)
DEFINE_PTY NAME(PasswordChar) GET(*AUTO #PasswordChar) SET(*AUTO #PasswordChar)
DEFINE_PTY NAME(Required) GET(*AUTO #RequiredField) SET(*AUTO #RequiredField)

* =======================================================
* Event Definitions
* =======================================================
DEFINE_EVT NAME(Changed)
DEFINE_EVT NAME(GotFocus)
DEFINE_EVT NAME(LostFocus)
DEFINE_EVT NAME(KeyPress)
DEFINE_MAP FOR(*OUTPUT) CLASS(#STD_FLAG) NAME(#KeyCode)
DEFINE_MAP FOR(*OUTPUT) CLASS(#STD_FLAG) NAME(#Char)
DEFINE_MAP FOR(*OUTPUT) CLASS(#PRIM_BOLN) NAME(#IsAltDown)
DEFINE_MAP FOR(*OUTPUT) CLASS(#PRIM_BOLN) NAME(#IsControlDown)
DEFINE_MAP FOR(*OUTPUT) CLASS(#PRIM_BOLN) NAME(#IsShiftDown)
DEFINE_MAP FOR(*BOTH) CLASS(#PRIM_BOLN) NAME(#Handled)

* =======================================================
* Property Routines
* =======================================================
PTYROUTINE NAME(SetValue)
DEFINE_MAP FOR(*INPUT) CLASS(#PRIM_VAR) NAME(#Value)
#EditBox.Value := #Value
#COM_OWNER.SetFieldPrompt
ENDROUTINE

PTYROUTINE NAME(GetValue)
DEFINE_MAP FOR(*OUTPUT) CLASS(#PRIM_VAR) NAME(#Value)
IF (#EditBox.Value <> #wDsc)
#Value := #EditBox.Value
ENDIF
ENDROUTINE

PTYROUTINE NAME(SetReadOnly)
DEFINE_MAP FOR(*INPUT) CLASS(#PRIM_BOLN) NAME(#ReadOnly)
#EditBox.ReadOnly := #ReadOnly
#EditBox.AutoSelect := #ReadOnly.Not
#COM_OWNER.SetFieldPrompt
ENDROUTINE

PTYROUTINE NAME(GetReadOnly)
DEFINE_MAP FOR(*OUTPUT) CLASS(#PRIM_BOLN) NAME(#ReadOnly)
#ReadOnly := #EditBox.ReadOnly
ENDROUTINE

PTYROUTINE NAME(SetShowError)
DEFINE_MAP FOR(*INPUT) CLASS(#PRIM_BOLN) NAME(#ShowError)
#EditBox.ShowError := #ShowError
#COM_OWNER.SetFieldPrompt
ENDROUTINE

PTYROUTINE NAME(GetShowError)
DEFINE_MAP FOR(*OUTPUT) CLASS(#PRIM_BOLN) NAME(#ShowError)
#ShowError := #EditBox.ShowError
ENDROUTINE

* =======================================================
* Event Routines
* =======================================================
EVTROUTINE HANDLING(#COM_OWNER.CreateInstance) OPTIONS(*NOCLEARMESSAGES *NOCLEARERRORS)
SET COM(#COM_OWNER) VISUALSTYLE(#VSSITAGRY)
#wNme := #COM_OWNER.ComponentPatternName
USE BUILTIN(GET_FIELD) WITH_ARGS(#wNme) TO_GET(#wRet #wTyp #wLen #wDec #wRef #wDsc #wLbl #wHdg #wOut #wInp)
IF (#COM_SELF.ComponentTag <> ”)
#wDsc := #COM_SELF.ComponentTag
ENDIF
ENDROUTINE

EVTROUTINE HANDLING(#EditBox.KeyPress) OPTIONS(*NOCLEARMESSAGES *NOCLEARERRORS) KEYCODE(#KeyCode) CHAR(#Character) HANDLED(#Handled) ISALTDOWN(#AltDown) ISSHIFTDOWN(#ShiftDown) ISCONTROLDOWN(#ControlDown)
DEFINE_COM CLASS(#STD_FLAG) NAME(#KeyedCharacter)
IF ((*Not #Handled) *And (*Not #EditBox.ReadOnly))
IF (#KeyCode = IsChar)
#KeyedCharacter := #Character
IF (*Not #wInp.Uppercase.Contains( ‘LC’ ))
#KeyedCharacter := #KeyedCharacter.Uppercase
ENDIF
#Handled := True
IF (#EditBox.Value = #wDsc)
#wChr := #EditBox.SelectionEnd
#EditBox.Value := #KeyedCharacter
ELSE
IF (#EditBox.SelectionEnd <> #EditBox.SelectionStart)
IF (#EditBox.SelectionEnd > #EditBox.SelectionStart)
#wChr := #EditBox.SelectionStart
#EditBox.Value := #EditBox.Value.Replace( #EditBox.Value.Substring( #EditBox.SelectionStart (#EditBox.SelectionEnd – #EditBox.SelectionStart) ) #KeyedCharacter )
ELSE
#wChr := #EditBox.SelectionEnd
#EditBox.Value := #EditBox.Value.Replace( #EditBox.Value.Substring( #EditBox.SelectionEnd (#EditBox.SelectionStart – #EditBox.SelectionEnd) ) #KeyedCharacter )
ENDIF
ELSE
#wChr := #EditBox.SelectionEnd
#EditBox.Value := #EditBox.Value.InsertString( #KeyedCharacter #EditBox.SelectionEnd )
ENDIF
ENDIF
#EditBox.SelectionStart #EditBox.SelectionEnd := #wChr + 1
#COM_OWNER.SetFieldPrompt
SIGNAL EVENT(Changed)
ENDIF
ENDIF
SIGNAL EVENT(KeyPress) KEYCODE(#KeyCode) CHAR(#KeyedCharacter) ISALTDOWN(#AltDown) ISCONTROLDOWN(#ControlDown) ISSHIFTDOWN(#ShiftDown) HANDLED(#Handled)
ENDROUTINE

EVTROUTINE HANDLING(#EditBox.Changed) OPTIONS(*NOCLEARMESSAGES *NOCLEARERRORS)
#COM_OWNER.SetFieldPrompt
SIGNAL EVENT(Changed)
ENDROUTINE

EVTROUTINE HANDLING(#EditBox.GotFocus) OPTIONS(*NOCLEARMESSAGES *NOCLEARERRORS)
SIGNAL EVENT(GotFocus)
ENDROUTINE

EVTROUTINE HANDLING(#EditBox.LostFocus) OPTIONS(*NOCLEARMESSAGES *NOCLEARERRORS)
SIGNAL EVENT(LostFocus)
ENDROUTINE

* =======================================================
* Method Routines
* =======================================================
MTHROUTINE NAME(SetFieldPrompt)
IF (#EditBox.Value.CurChars > 0)
IF (#EditBox.Value = #wDsc)
#EditBox.PasswordChar := ”
IF (#RequiredField)
#EditBox.VisualStyle <= #VSSITARED
ELSE
#EditBox.VisualStyle <= #VSSITAGRY
ENDIF
ELSE
#EditBox.PasswordChar := #PasswordChar
#EditBox.VisualStyle <= #VSSNRMBLK
ENDIF
ELSE
#EditBox.PasswordChar := ”
#EditBox.Value := #wDsc
#EditBox.VisualStyle <= #VSSITAGRY
ENDIF
ENDROUTINE

END_COM

Field Visualization Definition Code:

BEGIN_COM ROLE(*EXTENDS #PRIM_OBJT)
BEGIN_COM ROLE(*Visual #PRIM_EVEF) NAME(#VisualEdit) DEFAULTVISUAL(True) HEIGHT(18) MARGINLEFT(100) USEPICKLIST(False) WIDTH(200)
END_COM
BEGIN_COM ROLE(*Visual_Part #OBJFLDPRM) NAME(#VisualPrompt)
END_COM
END_COM

Normal Visual Style Code:

BEGIN_COM ROLE(*EXTENDS #PRIM_VS) DEFAULT(#SCHEME)
DEFINE_COM CLASS(#PRIM_VSS) NAME(#SCHEME) CAPTIONS(#CAPTION) TITLES(#CAPTION) VALUES(#VALUE)
DEFINE_COM CLASS(#PRIM_VSI) NAME(#CAPTION) FACENAME(‘Tahoma’) FONTSIZE(8) NORMBACKCOLOR(ButtonFace) TEXTCOLOR(Black)
DEFINE_COM CLASS(#PRIM_VSI) NAME(#VALUE) ALTERNBACKCOLOR(Window) BORDERSTYLE(3DLeft) FACENAME(‘Tahoma’) FONTSIZE(8) TEXTCOLOR(Black)
END_COM

Italic Gray Visual Style Code:

BEGIN_COM ROLE(*EXTENDS #PRIM_VS) DEFAULT(#SCHEME)
DEFINE_COM CLASS(#PRIM_VSS) NAME(#SCHEME) CAPTIONS(#CAPTION) TITLES(#CAPTION) VALUES(#VALUE)
DEFINE_COM CLASS(#PRIM_VSI) NAME(#CAPTION) FACENAME(‘Tahoma’) FONTSIZE(8) NORMBACKCOLOR(ButtonFace) TEXTCOLOR(Black)
DEFINE_COM CLASS(#PRIM_VSI) NAME(#VALUE) ALTERNBACKCOLOR(Window) BORDERSTYLE(3DLeft) FACENAME(‘Tahoma’) FONTSIZE(8) ITALIC(True) TEXTCOLOR(Gray)
END_COM

Italic Red Visual Style Code:

BEGIN_COM ROLE(*EXTENDS #PRIM_VS) DEFAULT(#SCHEME)
DEFINE_COM CLASS(#PRIM_VSS) NAME(#SCHEME) CAPTIONS(#CAPTION) TITLES(#CAPTION) VALUES(#VALUE)
DEFINE_COM CLASS(#PRIM_VSI) NAME(#CAPTION) FACENAME(‘Tahoma’) FONTSIZE(8) NORMBACKCOLOR(ButtonFace) TEXTCOLOR(Black)
DEFINE_COM CLASS(#PRIM_VSI) NAME(#VALUE) ALTERNBACKCOLOR(Window) BORDERSTYLE(3DLeft) FACENAME(‘Tahoma’) FONTSIZE(8) ITALIC(True) TEXTCOLOR(Red)
END_COM

Running Lansa as a Windows Service

I have seen the question of how to run a Lansa function as a Windows Service posted may times in various online forums. The Lansa executable (X_RUN.exe) does not have the entry and exit points for the Windows Service Controller. There are third-party application available for running an executable as a program, but they are not lightweight and they cost money. I solved this problem by creating a simple C# solution in Visual Studio 2010.

The Generic Windows Service Solution creates a process object with configurable command line arguments. In order to run a Lansa function as a service the command line is specified as the path to X_RUN.exe in the system executable folder and the command line arguments are the X_RUN arguments. The Lansa function can execute in a loop with a brief pause using the OV_SLEEP BIF. The Lansa function should not loop without a delay as the executing function will consume increasing system memory without giving the operating system the opportunity to reclaim resources. The service can be configured to either terminate when the process exits or restart the process if it is terminated.

The Generic Windows Service and/or Visual Studio 2010 Solution can be downloaded from the files section of the Yahoo Lansa User Group at http://tech.groups.yahoo.com/group/lansa2/files/. You must be a member of the group to download from the files section. The Windows Service is in the GenericService.zip file and includes batch files for installing and configuring the service.

Below is the C# source  code for the Generic Windows Service solution:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Timers;
using System.Configuration;

namespace LansaService
{
public partial class LansaService : ServiceBase
{

Process LansaProc = new Process();
Timer LansaTimer = new Timer();
bool LansaRestart = true;

public LansaService()
{
InitializeComponent();
}

protected override void OnStart(string[] args)
{

LansaRestart = Convert.ToBoolean( ConfigurationSettings.AppSettings[“Restart”].ToString());
startLansa();

}

private bool startLansa()
{

LansaTimer.Stop();
LansaProc.StartInfo.WorkingDirectory = ConfigurationSettings.AppSettings[“WorkingDirectory”].ToString();
LansaProc.StartInfo.FileName = ConfigurationSettings.AppSettings[“ExecutablePath”].ToString();
LansaProc.StartInfo.Arguments = ConfigurationSettings.AppSettings[“Arguments”].ToString();
LansaProc.StartInfo.UseShellExecute = false;
LansaProc.StartInfo.RedirectStandardOutput = false;
LansaProc.StartInfo.RedirectStandardError = false;

if (LansaProc.Start())
{
LansaTimer.Interval = 5000;
LansaTimer.Elapsed += new ElapsedEventHandler(LansaTimer_Elapsed);
LansaTimer.Start();
return true;
}
else
{
OnStop();
return false;
}

}

void LansaTimer_Elapsed(object sender, ElapsedEventArgs e)
{

if (LansaProc.HasExited)
{
if (LansaRestart)
{
startLansa();
}
else
{
OnStop();
}

}

}

protected override void OnStop()
{
try
{
LansaProc.Kill();
}
catch (Exception)
{
}
}
}
}

Understanding Component Scope

In Visual Lansa the concept of  component scope is often misunderstood. I have come across many component definitions that misuse the scope parameter. Often, it is because definitions are copied between Owner Components that do not function the same way and analysis is not done to evaluate the proper component scope.

A defined component in Visual Lansa may be given different levels of Scope within the application; “The SCOPE parameter is used to create component instances that are shared between different instances of component owners” (LANSA User Assistance V11 SP5, Technical Reference Guide 8.4.1). The SCOPE parameter can be specified as *INSTANCE, *LOCAL, *DEFAULT, *SHARED, or *APPLICATION.

*INSTANCE – When a component is defined with parameter SCOPE(*INSTANCE) a new instance of the component is created for each owner component

*LOCAL – When a component is defined with parameter SCOPE(*LOCAL) a new instance of the component is created every time an Event, Method, or Property Routine is executed; as such, this value is only valid when the component is defined immediately after a EVTROUTINE, MTHROUTINE, or PTYROUTINE command.

*DEFAULT – When a component is defined with parameter SCOPE(*DEFAULT) the value is determined from the position of the component definition. Components defined immediately after the BEGIN_COM command are interpreted as *INSTANCE, components defined immediately after EVTROUTINE, MTHROUTINE, or PTYROUTINE commands are interpreted as *LOCAL.

*SHARED – When a component is defined with parameter SCOPE(*SHARED) only one instance of the component is created for all owner components of the same class. Owner components of different classes do not share component instances defined as scope *SHARED.

*APPLICATION – When a component is defined with parameter SCOPE(*APPLICATION) only one instance of the component is created for all owner classes within the application, as such all DLL’s required to implement the defined component and owner component will remain in memory for the lifetime of the component instance and possibly the lifetime of the application.

The following is a visual illustration of different scoping parameters demonstrated with a visual component. The same principal applies for non-visual components. In these examples a parent form and child form(s) of different classes dynamically create instances of a calendar control.

SCOPE(*INSTANCE)

Instance

All components reference their own instance of the calendar control. As such, when a child component closes the reference to the calendar control is set to null and its DestroyInstance event is signaled. This allows the child forms handle count to reach zero at which point its own DestroyInstance event is signaled. The DLLs for both the calendar control and form will be unloaded during garbage cleanup.

SCOPE(*SHARED)

Shared

When the calendar control is defined as SCOPE(*SHARED) a new instance of the component is created for each owner component class; because Parent Form and Child Form are separate classes they do not share an instance of the calendar control. Notice that only one Child Form has a visible calendar control, because the calendar control is shared between the two like classes it can only be visible on one…because the calendar control can only have one owner component. This is not an issue for non-visual components but further illustrates the point that there is only one shared instance. In this case the calendar control will not be destroyed until its reference is set to *Null by both Child Forms, the DLLS for the child forms and calendar control will also not be unloaded until both references are set to *Null and both child forms are closed.

SCOPE(*APPLICATION)

Application
When the calendar control is defined as SCOPE(*APPLICATION) a single instance of the component is created for all components within the application (that are defined as SCOPE(*APPLICATION). The single component instance is shared regardless of owner component class. Owner components containing components defined as SCOPE(*APPLICATION) will not be destroyed (and DLLS will not be unloaded) until all references of the Defined Component within the application are set to *Null.

The first question to ask when determining the proper component scope is ‘Is the component used in multiple owner components?’ – If No, then the Defined Component should be SCOPE(*INSTANCE) when defined after a BEGIN_COM or SCOPE(*LOCAL) when defined within an event, property, or method routine…this is the default component scope.

If a component is used in multiple owner owner components ask ‘Are the Owner Components main features of the application that will exist as long as the application is running?’ – If No, then the Defined Component should be SCOPE(*INSTANCE) when defined after a BEGIN_COM or SCOPE(*LOCAL) when defined within an event, property, or method routine…this is the default component scope.

If the Owner Components are main application features that should share an instance of the Defined Component ask ‘Are the Owner Components of the same component class?’ – If Yes, then the Defined Component should be SCOPE(*SHARED); If No, the Defined Component should be SCOPE(*APPLICATION).

A great deal of thought must be given to the Scope parameter when defining components within a large application. Allowing components within an application to share instances of a component provides improved performance by avoiding multiple CreateInstance  routines, but it also may prevent DLLs from being unloaded and system resources being freed.

Poll Results: Lansa Version 12



Below are the reults for the recently posted poll regarding new features in Lansa Version 12:

Poll Results

I think that it is interesting that new SQL Database features head the list. I think this reflects the fact that even through all of the recent developments in presenting user’s with richer content and sophisticated interfaces Lansa developers are still constantly seeking the most efficient ways to transform data into information and present it to the end-user in a meaningful way.

Multi-Calendar Component

A recent post on the Yahoo Lansa Group asked about a date picker with a two month display. While there was not an easy way of using the Calendar primitive I had previously created a dynamic calendar control for other purposes. I was able to modify it slightly to allow for multiple months to be displayed and also allow for multiple dates to be selected.

The component illustrated below can be configures to display one to three calendars in an horizontal or vertical row. It can also be configured to select and return a single date or a date range where start and end dates are returned. Other normal calendar properties are configurable such as whether to show the current date and the first day of the week.

This calendar component also uses panels and buttons which will alter the display to match the current Lansa theme (#SYS_APPLN.Theme).

Multi-Calendar Component

The required components can be downloaded in zip format using the link below:

Click to Download Calendar Component

Poll: Lansa Version 12

A Microsoft Word Style Rich Text Memo Box

A Microsoft Word style Rich Text Memo Box has many possible uses within applications. When I first created this component it was to be used in a product specifications system where text instructions could be accompanied by diagrams. This component renders the rich-text in HTML using a lightweight ActiveX control from nBit information technologies (http://nbit.net.au/vpages.aspx?ID=HTML%20Editor%20OCX). In my original implementation the markup could then be converted to PDF for email or web delivery. There could be many additional uses for such a component: an editor for email templates as part of a automated mailing system, a way to add user-defined content into a WAM (CMS), etc .   

 

FUNCTION OPTIONS(*DIRECT)
BEGIN_COM ROLE(*EXTENDS #PRIM_PANL) Displayposition(1) Height(786) Layoutmanager(#ATLM_1) Left(0) Tabposition(1) Top(0) Width(938)

*  =======================================================
*  Component Definitions
*  =======================================================
DEFINE_COM CLASS(#STD_MEMO) NAME(#WorkText)
DEFINE_COM CLASS(#PRIM_ATLM) NAME(#ATLM_1)
DEFINE_COM CLASS(#VA_HTMLED.HTMLed) NAME(#VA_HTMLED) Displayposition(1) Height(769) Left(-3) Parent(#PANL_BACK) Tabposition(1) Top(-3) Visualstyle(#VS_WHITE9) Width(944)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#PANL_TOOLS) Displayposition(1) Height(24) Layoutmanager(#FWLM_1) Left(0) Parent(#PANL_TOP) Tabposition(1) Tabstop(False) Themestyle(Themed) Top(0) Visualstyleofparent(False) Width(807)
DEFINE_COM CLASS(#PRIM_ATLI) NAME(#ATLI_2) Attachment(Center) Manage(#PANL_TOOLS) Parent(#ATLM_1)
DEFINE_COM CLASS(#PRIM_ATLI) NAME(#ATLI_3) Attachment(Center) Manage(#VA_HTMLED) Marginbottom(-3) Marginleft(-3) Marginright(-3) Margintop(-3) Parent(#ATLM_1)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#PANL_BACK) Displayposition(1) Height(763) Layoutmanager(#ATLM_1) Left(0) Parent(#COM_OWNER) Tabposition(1) Tabstop(False) Top(23) Visualstyle(#VS_WHITE6) Width(938)
DEFINE_COM CLASS(#PRIM_ATLI) NAME(#ATLI_4) Attachment(Center) Manage(#PANL_BACK) Margintop(-1) Parent(#ATLM_1)
DEFINE_COM CLASS(#PRIM_FWLM) NAME(#FWLM_1) Flowoperation(Center) Flowoperationver(Center) Marginbottom(2) Marginleft(4) Spacing(2) Spacingitems(2)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BPASTE) Autosize(False) Buttonstyle(FlatButton) Componentversion(1) Displayposition(1) Height(20) Hint(‘Paste (CTRL + V)’) Image(#Q_PST) Left(4) Parent(#PANL_TOOLS) Tabposition(1) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_1) Manage(#BPASTE) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BCOPY) Autosize(False) Buttonstyle(FlatButton) Componentversion(1) Displayposition(2) Height(20) Hint(‘Copy (CTRL + C)’) Image(#Q_CPY) Left(26) Parent(#PANL_TOOLS) Tabposition(2) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_2) Manage(#BCOPY) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BCUT) Autosize(False) Buttonstyle(FlatButton) Componentversion(1) Displayposition(3) Height(20) Hint(‘Cut (CTRL + X)’) Image(#Q_CUT) Left(48) Parent(#PANL_TOOLS) Tabposition(3) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_3) Manage(#BCUT) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BBOLD) Autosize(False) Buttonstyle(FlatButton) Componentversion(1) Displayposition(5) Height(20) Hint(‘Bold Selection (CTRL + B)’) Image(#Q_BLD) Left(73) Parent(#PANL_TOOLS) Tabposition(4) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_4) Manage(#BBOLD) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BITALIC) Autosize(False) Buttonstyle(FlatButton) Componentversion(1) Displayposition(6) Height(20) Hint(‘Italic Selection (CTRL + I)’) Image(#Q_ITA) Left(95) Parent(#PANL_TOOLS) Tabposition(5) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_5) Manage(#BITALIC) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BUNDERLINE) Autosize(False) Buttonstyle(FlatButton) Componentversion(1) Displayposition(7) Height(20) Hint(‘Underline Selection (CTRL + U)’) Image(#Q_UND) Left(117) Parent(#PANL_TOOLS) Tabposition(6) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_6) Manage(#BUNDERLINE) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BSTRIKE) Autosize(False) Buttonstyle(FlatButton) Componentversion(1) Displayposition(8) Height(20) Hint(‘Strikethrough Selection’) Image(#Q_STR) Left(139) Parent(#PANL_TOOLS) Tabposition(7) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_7) Manage(#BSTRIKE) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BFONT) Autosize(False) Buttonstyle(FlatButton) Componentversion(1) Displayposition(10) Height(20) Hint(‘Custom Font’) Image(#Q_FNT) Left(164) Parent(#PANL_TOOLS) Tabposition(8) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_8) Manage(#BFONT) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BLEFT) Autosize(False) Buttonstyle(FlatButton) Componentversion(1) Displayposition(12) Height(20) Hint(‘Left Justify’) Image(#Q_LFT) Left(189) Parent(#PANL_TOOLS) Tabposition(9) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_9) Manage(#BLEFT) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BCENTER) Autosize(False) Buttonstyle(FlatButton) Componentversion(1) Displayposition(13) Height(20) Hint(‘Center Justify’) Image(#Q_CNT) Left(211) Parent(#PANL_TOOLS) Tabposition(10) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_10) Manage(#BCENTER) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BRIGHT) Autosize(False) Buttonstyle(FlatButton) Componentversion(1) Displayposition(14) Height(20) Hint(‘Right Justify’) Image(#Q_RGT) Left(233) Parent(#PANL_TOOLS) Tabposition(11) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_11) Manage(#BRIGHT) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BINDENT) Autosize(False) Buttonstyle(FlatButton) Componentversion(1) Displayposition(16) Height(20) Hint(‘Indent’) Image(#Q_IND) Left(258) Parent(#PANL_TOOLS) Tabposition(12) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_12) Manage(#BINDENT) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BOUTDENT) Autosize(False) Buttonstyle(FlatButton) Componentversion(1) Displayposition(17) Height(20) Hint(‘Outdent’) Image(#Q_OUT) Left(280) Parent(#PANL_TOOLS) Tabposition(13) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_13) Manage(#BOUTDENT) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BORDERED) Autosize(False) Buttonstyle(FlatButton) Componentversion(1) Displayposition(19) Height(20) Hint(‘Numbered List’) Image(#Q_ORD) Left(305) Parent(#PANL_TOOLS) Tabposition(14) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_14) Manage(#BORDERED) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BUNORDERED) Autosize(False) Buttonstyle(FlatButton) Componentversion(1) Displayposition(20) Height(20) Hint(‘Bullet List’) Image(#Q_UNO) Left(327) Parent(#PANL_TOOLS) Tabposition(15) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_15) Manage(#BUNORDERED) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BIMAGE) Autosize(False) Buttonstyle(FlatButton) Componentversion(1) Displayposition(22) Height(20) Hint(‘Insert Image’) Image(#Q_IMG) Left(352) Parent(#PANL_TOOLS) Tabposition(16) Top(1) Visible(False) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_16) Manage(#BIMAGE) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BUNDO) Autosize(False) Buttonstyle(FlatButton) Componentversion(1) Displayposition(26) Height(20) Hint(‘Undo (CTRL + Z)’) Image(#Q_UDO) Left(421) Parent(#PANL_TOOLS) Tabposition(19) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_17) Manage(#BUNDO) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BREDO) Autosize(False) Buttonstyle(FlatButton) Componentversion(1) Displayposition(27) Height(20) Hint(‘Redo (CTRL + Y)’) Image(#Q_RDO) Left(443) Parent(#PANL_TOOLS) Tabposition(20) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_18) Manage(#BREDO) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BSPELL) Autosize(False) Buttonstyle(FlatButton) Componentversion(1) Displayposition(29) Height(20) Hint(‘Check Spelling’) Image(#Q_SPL) Left(468) Parent(#PANL_TOOLS) Tabposition(21) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_19) Manage(#BSPELL) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_APPL.ICommonDialogFileOpen) NAME(#OpenDialog) REFERENCE(*DYNAMIC)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BLINK) Buttonstyle(FlatButton) Componentversion(1) Displayposition(23) Height(20) Hint(‘Insert Hyperlink’) Image(#Q_LNK) Left(374) Parent(#PANL_TOOLS) Tabposition(17) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_27) Manage(#BLINK) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_SPBN) NAME(#BTABLE) Buttonstyle(FlatButton) Componentversion(1) Displayposition(24) Height(20) Hint(‘Create Table’) Image(#Q_TBL) Left(396) Parent(#PANL_TOOLS) Tabposition(18) Top(1) Width(20)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_28) Manage(#BTABLE) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#SEP_1) Displayposition(4) Height(20) Left(70) Parent(#PANL_TOOLS) Tabposition(29) Tabstop(False) Themedrawstyle(LightTitle) Top(1) Width(1)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#SEP_2) Displayposition(11) Height(20) Left(186) Parent(#PANL_TOOLS) Tabposition(27) Tabstop(False) Themedrawstyle(LightTitle) Top(1) Width(1)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#SEP_3) Displayposition(9) Height(20) Left(161) Parent(#PANL_TOOLS) Tabposition(28) Tabstop(False) Themedrawstyle(LightTitle) Top(1) Width(1)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#SEP_4) Displayposition(15) Height(20) Left(255) Parent(#PANL_TOOLS) Tabposition(26) Tabstop(False) Themedrawstyle(LightTitle) Top(1) Width(1)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#SEP_5) Displayposition(18) Height(20) Left(302) Parent(#PANL_TOOLS) Tabposition(25) Tabstop(False) Themedrawstyle(LightTitle) Top(1) Width(1)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#SEP_6) Displayposition(21) Height(20) Left(349) Parent(#PANL_TOOLS) Tabposition(24) Tabstop(False) Themedrawstyle(LightTitle) Top(1) Width(1)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#SEP_7) Displayposition(25) Height(20) Left(418) Parent(#PANL_TOOLS) Tabposition(23) Tabstop(False) Themedrawstyle(LightTitle) Top(1) Width(1)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#SEP_8) Displayposition(28) Height(20) Left(465) Parent(#PANL_TOOLS) Tabposition(22) Tabstop(False) Themedrawstyle(LightTitle) Top(1) Width(1)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_20) Manage(#SEP_1) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_21) Manage(#SEP_2) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_22) Manage(#SEP_3) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_23) Manage(#SEP_4) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_24) Manage(#SEP_5) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_25) Manage(#SEP_6) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_26) Manage(#SEP_7) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_FWLI) NAME(#FWLI_42) Manage(#SEP_8) Parent(#FWLM_1)
DEFINE_COM CLASS(#PRIM_PANL) NAME(#PANL_TOP) Displayposition(2) Height(24) Left(0) Parent(#COM_OWNER) Tabposition(2) Tabstop(False) Themedrawstyle(Toolbar) Themestyle(Themed) Top(0) Visualstyle(#VS_WHITE9) Width(938)
DEFINE_COM CLASS(#PRIM_ATLI) NAME(#ATLI_1) Attachment(Top) Manage(#PANL_TOP) Parent(#ATLM_1)

*  =======================================================

*  Locally Defined Fields
*  =======================================================
DEFINE FIELD(#wOkPress) TYPE(*BOOLEAN)
DEFINE FIELD(#wReadOnly) TYPE(*BOOLEAN)
DEFINE FIELD(#wFixed) TYPE(*BOOLEAN)
DEFINE FIELD(#wToolbar) TYPE(*BOOLEAN)
DEFINE FIELD(#wFixDiv) TYPE(*STRING)
DEFINE FIELD(#wEndDiv) TYPE(*STRING)
DEFINE FIELD(#wChars) TYPE(*STRING)
DEFINE FIELD(#wFilePath) TYPE(*STRING)
DEFINE FIELD(#wFileName) REFFLD(#STD_PATH)
DEFINE FIELD(#wUserPath) REFFLD(#STD_PATH)
DEFINE FIELD(#wReturn) TYPE(*CHAR) LENGTH(2)

*  =======================================================
*  Events
*  =======================================================
DEFINE_EVT NAME(Changed)
DEFINE_EVT NAME(ImageAdded)

*  =======================================================

*  Properties
*  =======================================================
DEFINE_PTY NAME(OutputText) GET(GetOutputText) SET(SetOutputText)
DEFINE_PTY NAME(ShowToolbar) SET(SetShowToolbar)
DEFINE_PTY NAME(ImagePath) GET(*AUTO #STD_PATH) SET(SetImagePath)
DEFINE_PTY NAME(ReadOnly) GET(GetReadOnly) SET(SetReadOnly)
DEFINE_PTY NAME(FixedFont) GET(GetFixedFont) SET(SetFixedFont)
DEFINE_PTY NAME(ClipboardTools) GET(GetClipboardTools) SET(SetClipboardTools)
DEFINE_PTY NAME(AdvancedEditing) GET(GetAdvancedEditing) SET(SetAdvancedEditing)

*  =======================================================

*  Property Routines
*  =======================================================
PTYROUTINE NAME(GetOutputText)
DEFINE_MAP FOR(*OUTPUT) CLASS(#STD_MEMO) NAME(#oText)

* Loop through DocumentHTML character at a time to ignore low/high ASCII values
#STD_MEMO := #VA_HTMLED.DocumentHTML
BEGIN_LOOP USING(#STD_NUM) TO(#STD_MEMO.CurChars)
CONTINUE IF(#wChars.Contains( #STD_MEMO.Substring( #STD_NUM 1 ) ).Not)
#oText += #STD_MEMO.Substring( #STD_NUM 1 )
END_LOOP
ENDROUTINE

PTYROUTINE NAME(SetOutputText)
DEFINE_MAP FOR(*INPUT) CLASS(#STD_MEMO) NAME(#iText)

* Replace &nbsp; with ASCII space for proper word wrapping
#VA_HTMLED.DocumentHTML #WorkText := #iText.ReplaceAll( ‘ ‘ ‘ ‘ )

* Check if Text contains Fixed Width Default tag
IF (#VA_HTMLED.DocumentHTML.Contains( #wFixDiv ))
#COM_OWNER.FixedFont := True
ELSE
#COM_OWNER.FixedFont := False
ENDIF
ENDROUTINE

PTYROUTINE NAME(SetShowToolbar)
DEFINE_MAP FOR(*INPUT) CLASS(#PRIM_BOLN) NAME(#iShow)

* Hide/Show Markup Toolbar
#PANL_TOP.Visible #wToolbar := #iShow
ENDROUTINE

PTYROUTINE NAME(SetImagePath)
DEFINE_MAP FOR(*INPUT) CLASS(#STD_PATH) NAME(#iPath)

* Sets path to attach images from, do not allow images if not set
#STD_PATH := #iPath
IF (#STD_PATH = ”)
#BIMAGE.Visible := False
ELSE
#BIMAGE.Visible := True
ENDIF
ENDROUTINE

PTYROUTINE NAME(SetReadOnly)
DEFINE_MAP FOR(*INPUT) CLASS(#PRIM_BOLN) NAME(#iReadOnly)

* Set component to read only
IF (#iReadOnly)
#PANL_TOOLS.Visible := False
#VA_HTMLED.EditorEnabled := False
ELSE

* When set to Edit, check Show Toolbar property
IF (#wToolbar)
#PANL_TOOLS.Visible := True
ENDIF
#VA_HTMLED.EditorEnabled := True

* Restore Default CSSText property
#VA_HTMLED.CSSText := ‘body { font: 12px Arial, Tahoma, Verdana; color: #000000; background-color: rgb(255,255,255); } table { border: 1px solid #3B5E91; border-collapse: collapse; padding: 5px; font: 12px Arial, Tahoma, Verdana; color: #000000; background-color: rgb(255,255,255); } td { border: 1px solid #3B5E91; border-collapse: collapse; }’
ENDIF
#wReadOnly := #iReadOnly
ENDROUTINE

PTYROUTINE NAME(GetReadOnly)
DEFINE_MAP FOR(*OUTPUT) CLASS(#PRIM_BOLN) NAME(#oReadOnly)
IF (#wReadOnly <> True)
#wReadOnly := False
ENDIF
#oReadOnly := #wReadOnly
ENDROUTINE

PTYROUTINE NAME(SetFixedFont)
DEFINE_MAP FOR(*INPUT) CLASS(#PRIM_BOLN) NAME(#iFixedFont)

* Set Default fon to Fixed Width
IF (#iFixedFont)
IF (#VA_HTMLED.DocumentHTML.Contains( #wFixDiv ).Not)
#VA_HTMLED.DocumentHTML := #wFixDiv + #VA_HTMLED.DocumentHTML + #wEndDiv
ENDIF
ELSE
IF (#VA_HTMLED.DocumentHTML.Contains( #wFixDiv ))
#VA_HTMLED.DocumentHTML := #VA_HTMLED.DocumentHTML.LeftTrim( #wFixDiv ).RightTrim( #wEndDiv )
ENDIF
ENDIF
#wFixed := #iFixedFont
ENDROUTINE

PTYROUTINE NAME(GetFixedFont)
DEFINE_MAP FOR(*OUTPUT) CLASS(#PRIM_BOLN) NAME(#oFixedFont)

* Return FixedFont Property
#oFixedFont := #wFixed
ENDROUTINE

PTYROUTINE NAME(SetClipboardTools)
DEFINE_MAP FOR(*INPUT) CLASS(#PRIM_BOLN) NAME(#iClipboardTools)

* Hide/Show Clipboard Button
#BCUT.Visible #BCOPY.Visible #BPASTE.Visible #SEP_1.Visible := #iClipboardTools
ENDROUTINE

PTYROUTINE NAME(GetClipboardTools)
DEFINE_MAP FOR(*OUTPUT) CLASS(#PRIM_BOLN) NAME(#oClipboardTools)

* Return ClipboardTools Property
#oClipboardTools := #BCUT.Visible
ENDROUTINE

PTYROUTINE NAME(SetAdvancedEditing)
DEFINE_MAP FOR(*INPUT) CLASS(#PRIM_BOLN) NAME(#iAdvancedEditing)

* Hide/Show Advanced Editing Features
#SEP_4.Visible #SEP_6.Visible #SEP_7.Visible #SEP_8.Visible #BINDENT.Visible #BOUTDENT.Visible #BIMAGE.Visible #BLINK.Visible #BTABLE.Visible #BUNDO.Visible #BREDO.Visible #BSPELL.Visible := #iAdvancedEditing
ENDROUTINE

PTYROUTINE NAME(GetAdvancedEditing)
DEFINE_MAP FOR(*OUTPUT) CLASS(#PRIM_BOLN) NAME(#oAdvancedEditing)

* Return AdvancedEditing Property
#oAdvancedEditing := #BSPELL.Visible
ENDROUTINE

*  =======================================================
*  Event Routines
*  =======================================================
EVTROUTINE HANDLING(#COM_OWNER.CreateInstance) OPTIONS(*NOCLEARMESSAGES *NOCLEARERRORS)

* Set Initial Values for Local Fields
#wChars := *QUOTE.Concat( ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 1234567890`~!@#$%^&*()-_=+[]{}\|;:”/?.>,<‘ )
#wFixDiv := ‘
#wEndDiv := ‘</div>’
#wToolbar := True
#wReadOnly := False
#wFixed := False
ENDROUTINE

EVTROUTINE HANDLING(#COM_OWNER.Initialize) OPTIONS(*NOCLEARMESSAGES *NOCLEARERRORS)
#VA_HTMLED.Realize

* Hide Editor Context Menu Options
#VA_HTMLED.HiddenContextMenus := ‘MiscSource;MiscStyle;MiscRevert;ImgNewLink;ImgLinkRemove;ImgLink;Links;LinkCut;LinkCopy;LinkPaste;LinkEdit;LinkRemove;’

* Set CSS Text
#VA_HTMLED.CSSText := ‘body { font: 12px Arial, Tahoma, Verdana; color: #000000; background-color: rgb(255,255,255); } table { border: 1px solid #3B5E91; border-collapse: collapse; padding: 5px; font: 12px Arial, Tahoma, Verdana; color: #000000; background-color: rgb(255,255,255); } td { border: 1px solid #3B5E91; border-collapse: collapse; }’
ENDROUTINE

EVTROUTINE HANDLING(#BPASTE.Click)
#COM_OWNER.PasteClipboard
ENDROUTINE

MTHROUTINE NAME(PasteClipboard)

* Paste from Windows clipboard
#VA_HTMLED.paste_document

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BCOPY.Click)
#COM_OWNER.CopyClipboard
ENDROUTINE

MTHROUTINE NAME(CopyClipboard)

* Copy to Windows clipboard
#VA_HTMLED.copy_document

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BCUT.Click)
#COM_OWNER.CutClipboard
ENDROUTINE

MTHROUTINE NAME(CutClipboard)
* Cut to Windows clipboard
#VA_HTMLED.cut_document

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BBOLD.Click)
#COM_OWNER.BoldText
ENDROUTINE

MTHROUTINE NAME(BoldText)

* Bold selected text
#VA_HTMLED.bold_document

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BITALIC.Click)
#COM_OWNER.ItalicText
ENDROUTINE

MTHROUTINE NAME(ItalicText)

* Italic selected text
#VA_HTMLED.italic_document

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BUNDERLINE.Click)
#COM_OWNER.UnderlineText
ENDROUTINE

MTHROUTINE NAME(UnderlineText)

* Underline selected text
#VA_HTMLED.underline_document

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BSTRIKE.Click)
#COM_OWNER.StrikethroughText
ENDROUTINE

MTHROUTINE NAME(StrikethroughText)

* Strikethrough selected text
#VA_HTMLED.strike_document

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BFONT.Click)
#COM_OWNER.CustomFont
ENDROUTINE

MTHROUTINE NAME(CustomFont)

* Customize font settings
#VA_HTMLED.change_Font

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BLEFT.Click)
#COM_OWNER.LeftJustify
ENDROUTINE

MTHROUTINE NAME(LeftJustify)

* Left Align
#VA_HTMLED.Left_Justify

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BCENTER.Click)
#COM_OWNER.CenterJustify
ENDROUTINE

MTHROUTINE NAME(CenterJustify)

* Center Align
#VA_HTMLED.Center_Justify

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BRIGHT.Click)
#COM_OWNER.RightJustify
ENDROUTINE

MTHROUTINE NAME(RightJustify)

* Right Align
#VA_HTMLED.Right_Justify

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BINDENT.Click)
#COM_OWNER.IndentText
ENDROUTINE

MTHROUTINE NAME(IndentText)

* Indents entire block element (<p><div>)
#VA_HTMLED.indent_document

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BOUTDENT.Click)
#COM_OWNER.OutdentText
ENDROUTINE

MTHROUTINE NAME(OutdentText)

* Unindents entire block element (
#VA_HTMLED.unindent_document

)

 

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BORDERED.Click)
#COM_OWNER.OrderedList
ENDROUTINE

MTHROUTINE NAME(OrderedList)

* Create Numbered List
#VA_HTMLED.numbered_list

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BUNORDERED.Click)
#COM_OWNER.UnorderedList
ENDROUTINE

MTHROUTINE NAME(UnorderedList)

* Create Unnmbered List (Bullets)
#VA_HTMLED.unnumbered_list

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BIMAGE.Click)
#COM_OWNER.InsertImage
ENDROUTINE

MTHROUTINE NAME(InsertImage)

* Insert Image from File
INVOKE METHOD(#SYS_APPLN.CreateFileOpenDialog) Result(#OpenDialog)
#OpenDialog.Title := ‘Select File’
#OpenDialog.HideReadOnly := False
#OpenDialog.ExplorerStyle := True

* Set Initial Path to ImagePath property
#OpenDialog.InitialDir := #STD_PATH
#OpenDialog.MultiSelect := False
INVOKE METHOD(#OpenDialog.Show) Okpressed(#wOkPress)
IF ((#wOkPress) *And (#OpenDialog.FileCount = 0))

* Image was selected
#wFilePath := #OpenDialog.File
IF (#wFilePath.Contains( ‘\’ ))
#wUserPath := #wFilePath.Substring( 1 (#wFilePath.LastPositionOf( ‘\’ )) )
#wFileName := #wFilePath.Substring( (#wFilePath.LastPositionOf( ‘\’ ) + 1) )
IF (#wUserPath <> #STD_PATH)
USE BUILTIN(OV_FILE_SERVICE) WITH_ARGS(COPY_FILE #wFilePath (#STD_PATH + #wFileName)) TO_GET(#wReturn)
IF (#wReturn = ‘OK’)
SIGNAL EVENT(ImageAdded)
#wFilePath := (#STD_PATH + #wFileName)
ENDIF
ENDIF
ELSE
IF (#wFilePath.Contains( ‘/’ ))
#wUserPath := #wFilePath.Substring( 1 (#wFilePath.LastPositionOf( ‘/’ )) )
#wFileName := #wFilePath.Substring( (#wFilePath.LastPositionOf( ‘/’ ) + 1) )
IF (#wUserPath <> #STD_PATH)
USE BUILTIN(OV_FILE_SERVICE) WITH_ARGS(COPY_FILE #wFilePath (#STD_PATH + #wFileName)) TO_GET(#wReturn)
IF (#wReturn = ‘OK’)
SIGNAL EVENT(ImageAdded)
#wFilePath := (#STD_PATH + #wFileName)
ENDIF
ENDIF
ENDIF
ENDIF

* This code provided for storing images on web-facing IFS path: 
* Format  image path using proper http path ensures images will be visible on any HTML/PDF printouts
* IF (#wFilePath.Uppercase.Contains( ‘//LocalSystemI’ ))
* #wFilePath := #wFilePath.Lowercase.Replace( ‘LocalSystemI’ ‘server.domain.com’ )
* ELSE
*IF (#wFilePath.Uppercase.Contains( ‘\\LocalSystemI’ ))
*#wFilePath := #wFilePath.Lowercase.ReplaceAll( ‘\’ ‘/’ ).ReplaceAll( ‘LocalSystemI’ ‘server.domain.com’ )
*ENDIF
*ENDIF#VA_HTMLED.insertImageFromURL( #wFilePath )
*ENDIF

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BLINK.Click)
#COM_OWNER.InsertLink
ENDROUTINE

MTHROUTINE NAME(InsertLink)

* Create Hyperlink
#VA_HTMLED.insert_Link

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BTABLE.Click)
#COM_OWNER.InsertTable
ENDROUTINE

MTHROUTINE NAME(InsertTable)

* Displays the Rich-Text component’s inert HTML table dialog
#VA_HTMLED.Table_Document

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BUNDO.Click)
#COM_OWNER.Undo
ENDROUTINE

MTHROUTINE NAME(Undo)

* Undo (CTRL + Z)
#VA_HTMLED.undo_document

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BREDO.Click)
#COM_OWNER.Redo
ENDROUTINE

MTHROUTINE NAME(Redo)

* Redo (CTRL + Y)
#VA_HTMLED.redo_document

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

EVTROUTINE HANDLING(#BSPELL.Click)
#COM_OWNER.CheckSpelling
ENDROUTINE

MTHROUTINE NAME(CheckSpelling)

* Spellcheck document
#VA_HTMLED.SpellCheck
ENDROUTINE

EVTROUTINE HANDLING(#VA_HTMLED.ASCIIKeyPress) OPTIONS(*NOCLEARMESSAGES *NOCLEARERRORS)

* Check for Changes
#COM_OWNER.CheckChanges
ENDROUTINE

MTHROUTINE NAME(CheckChanges)

* Signal Changed on Change of Output Text
IF (#VA_HTMLED.DocumentHTML <> #WorkText)
SIGNAL EVENT(Changed)
#WorkText := #VA_HTMLED.DocumentHTML
ENDIF
ENDROUTINE

END_COM
 

Follow

Get every new post delivered to your Inbox.

Join 43 other followers