2.16.3.6 例5:動的なボタンの作成

プログラムでは、アクションでコレクションを作成して組み込み、他のコンポーネントにコレクションを渡して処理し、最後にコレクションを破棄する必要がある場面が数多くあります。

この例では、ボタンのコレクションを動的に作成し、操作し、すべてのボタンをメモリから破棄する方法を説明します。

動的なコレクション

この例では、最初にボタンの動的なコレクションを作成します。

 

DEFINE_COM class(#PRIM_KCOL<#prim_phbn #STD_NUM>) name(#BUTTON_COLLECTION) reference(*DYNAMIC)  STYLE(Collection)

reference(*DYNAMIC)を指定すると、フォームがロードされるとき(通常のDEFINE_COMステートメントではこうなる)ではなく、明示的に参照が作成されるときにのみコレクションを作成するようLANSAに指示します。コレクションを明示的に作成する利点は、後になって好きなときに参照を*NULLに設定して破棄できることです。

実行時に作成されるコレクションとボタン

実行時に、ユーザーが作成するボタンの数を入力し、Create Buttonsボタンをクリックした場合にコレクションが存在しないときは、SET_REFコマンドを使用して作成されます。

 

IF_REF com(#BUTTON_COLLECTION) is(*null)

SET_REF com(#BUTTON_COLLECTION) to(*Create_as #PRIM_KCOL<#prim_phbn #STD_NUM>)
 
ENDIF 

 

そして#STD_NUMフィールドで指定された数のボタンがコレクション内に作成されます。

 

BEGIN_LOOP to(#STD_NUM)
 
CHANGE field(#BUTTINDEX) to('#ButtIndex + 1')
USE builtin(BCONCAT) with_args('Push Button' #BUTTCHAR) to_get(#STD_TEXTL)
SET_REF com(#Button_collection<#ButtIndex>) to(*CREATE_AS #PRIM_PHBN)
SET com(#BUTTON_COLLECTION<#ButtIndex>) PARENT(#Button_Panel) WIDTH(120) CAPTION(#Std_TextL)
 
END_LOOP

 

最後に、実際に作成されます。

 

* Realize all the buttons just created.You can do this button by button
* but it is more efficient to do them all in one go by (re)realizing their parent ....
 
INVOKE method(#Button_Panel.Realize)
 

コレクションの破棄

コレクション内のすべてのボタンは、ユーザーがコレクション全体の参照を*NULLに設定するDestroy all Buttonsをクリックすると破棄されます。

 

EVTROUTINE handling(#DESTROY_BUTTON.Click)
SET_REF com(#BUTTON_COLLECTION) to(*null)
ENDROUTINE

 

コレクションの例5のソース・コード

FUNCTION options(*DIRECT)

BEGIN_COM ROLE(*EXTENDS #PRIM_FORM) CAPTION('Setting References') HEIGHT(324) LEFT(353) TOP(146) VISUALSTYLE(#VS_NORM) WIDTH(643)
 
* Form layout and button details
 
DEFINE_COM CLASS(#PRIM_PANL) NAME(#BUTTON_PANEL) DISPLAYPOSITION(1) HEIGHT(194) LAYOUTMANAGER(#BUTTON_PANEL_FLOW) LEFT(32) PARENT(#COM_OWNER) TABPOSITION(1) TABSTOP(False) TOP(72) WIDTH(569)
DEFINE_COM CLASS(#PRIM_FWLM) NAME(#BUTTON_PANEL_FLOW) FLOWOPERATION(Center) FLOWOPERATIONHOR(Spread)
DEFINE_COM CLASS(#STD_NUM.Visual) NAME(#STD_NUM) CAPTION('Number of buttons to Create') DISPLAYPOSITION(2) HEIGHT(19) LABELTYPE(Caption) LEFT(24) PARENT(#COM_OWNER) TABPOSITION(2) TOP(16) WIDTH(193)
DEFINE_COM CLASS(#PRIM_PHBN) NAME(#CREATE_BUTTON) CAPTION('Create Buttons') DISPLAYPOSITION(3) LEFT(232) PARENT(#COM_OWNER) TABPOSITION(3) TOP(16)
DEFINE_COM CLASS(#PRIM_PHBN) NAME(#DESTROY_BUTTON) CAPTION('Destroy all Buttons') DISPLAYPOSITION(4) LEFT(318) PARENT(#COM_OWNER) TABPOSITION(4) TOP(16) WIDTH(97)
DEFINE_COM CLASS(#PRIM_PHBN) NAME(#ENABLE_BUTTON) CAPTION('Enable All Buttons') DISPLAYPOSITION(5) LEFT(422) PARENT(#COM_OWNER) TABPOSITION(5) TOP(16) WIDTH(97)
DEFINE_COM CLASS(#PRIM_PHBN) NAME(#DISABLE_BUTTON) CAPTION('Disable All Buttons') DISPLAYPOSITION(6) LEFT(526) PARENT(#COM_OWNER) TABPOSITION(6) TOP(16) WIDTH(96)
 
* Keep an index to the number of buttons created, also in character format so that it can be used in the button caption later
 
DEFINE field(#BUTTINDEX) length(7) decimals(0) reffld(#DATE) edit_code(4) default(0)
DEFINE field(#BUTTCHAR) type(*CHAR) length(7) to_overlay(#BUTTINDEX)
 
* Keyed collections required to track buttons and flow manager items dynamically created
 
DEFINE_COM class(#PRIM_KCOL<#prim_phbn #STD_NUM>) name(#BUTTON_COLLECTION) reference(*DYNAMIC)  STYLE(Collection)
DEFINE_COM class(#PRIM_KCOL<#prim_fwli #STD_NUM>) name(#FLOWITEM_COLLECTION) reference(*DYNAMIC) STYLE(Collection)
 
* =================================================
* Handle Form Create instance
* =================================================
 
EVTROUTINE handling(#Com_Owner.CreateInstance)
SET com(#Std_Num) VALUE(3)
ENDROUTINE
 
* ===============================================
* Handle number of buttons to create being set to silly values
* ===============================================
EVTROUTINE handling(#Std_Num.Changed)
 
CASE of_field(#STD_NUM)
WHEN value_is('< 0')
SET com(#Std_Num) VALUE(1)
WHEN value_is('> 50')
SET com(#Std_Num) VALUE(50)
ENDCASE
 
ENDROUTINE
 
* =================================================
* Handle click of the button asking to dynamically create buttons
* =================================================
EVTROUTINE handling(#CREATE_BUTTON.Click)
 
* If the required keyed collections do not currently exist then create them now
 
IF_REF com(#BUTTON_COLLECTION) is(*null)
SET_REF com(#BUTTON_COLLECTION) to(*Create_as #PRIM_KCOL<#prim_phbn #STD_NUM>)
SET_REF com(#FLOWITEM_COLLECTION) to(*Create_as #Prim_KCol<#PRIM_FWLI #STD_NUM>)
ENDIF
 
* Now create the requested number of buttons and keep track
* of them in the keyed collections ....
 
BEGIN_LOOP to(#STD_NUM)
 
CHANGE field(#BUTTINDEX) to('#ButtIndex + 1')
USE builtin(BCONCAT) with_args('Push Button' #BUTTCHAR) to_get(#STD_TEXTL)
SET_REF com(#Button_collection<#ButtIndex>) to(*CREATE_AS #PRIM_PHBN)
SET com(#BUTTON_COLLECTION<#ButtIndex>) PARENT(#Button_Panel) WIDTH(120) CAPTION(#Std_TextL)
 
* Dynamically create a new flow layout item for the button and set up its details.
* Keep a reference to it in the flow item keyed collection.
 
SET_REF com(#FlowItem_Collection<#ButtIndex>) to(*CREATE_AS #PRIM_FWLI)
SET com(#FlowItem_Collection<#ButtIndex>) PARENT(#Button_Panel_Flow) MANAGE(#BUTTON_COLLECTION<#ButtIndex>)
 
END_LOOP
 
* Realize all the buttons just created.You can do this button by button
* but it is more efficient to do them all in one go by (re)realizing their parent ....
 
INVOKE method(#Button_Panel.Realize)
 
ENDROUTINE
 
* =================================
* Handle request to destroy all buttons
* =================================
 
EVTROUTINE handling(#DESTROY_BUTTON.Click)
 
* Destroy the button and flow item collections which will cause
* all the referenced items in the collection to be destroyed as well
 
SET_REF com(#FLOWITEM_COLLECTION) to(*null)
SET_REF com(#BUTTON_COLLECTION) to(*null)
 
* Reset the button index to zero .....
 
CHANGE field(#BUTTINDEX) to(0)
 
ENDROUTINE
 
* =================================
* Handle request to enable all buttons
* =================================
 
EVTROUTINE handling(#ENABLE_BUTTON.Click)
 
* If a button collection currently exists enable all the button in it ...
 
IF_REF com(#BUTTON_COLLECTION) is_not(*null)
SET com(#BUTTON_COLLECTION<>) ENABLED(True)
ENDIF
 
ENDROUTINE
 
* =================================
* Handle request to enable all buttons
* =================================
 
EVTROUTINE handling(#DISABLE_BUTTON.Click)
 
* If a button collection currently exists disable all the button in it ...
 
IF_REF com(#BUTTON_COLLECTION) is_not(*null)
SET com(#BUTTON_COLLECTION<>) ENABLED(False)
ENDIF
 
ENDROUTINE
 
* =====================================================================
* Handle click of one of the created buttons by listening to the entire collection of buttons
* =====================================================================
 
EVTROUTINE handling(#BUTTON_COLLECTION<>.Click) com_sender(#ClickedButton)
USE builtin(BCONCAT) with_args('You just clicked' #CLICKEDBUTTON.CAPTION) to_get(#STD_TEXTL)
USE builtin(MESSAGE_BOX_SHOW) with_args(OK OK INFO *COMPONENT #STD_TEXTL)
ENDROUTINE
 
END_COM