Curl Global Community
複合コントロールのコンストラクタ - Printable Version

+- Curl Global Community (https://communities.curl.com)
+-- Forum: Discussions (https://communities.curl.com/forumdisplay.php?fid=1)
+--- Forum: General Curl questions (https://communities.curl.com/forumdisplay.php?fid=2)
+--- Thread: 複合コントロールのコンストラクタ (/showthread.php?tid=883)



複合コントロールのコンストラクタ - umemura - 04-03-2013

ファイル参照用のコントロールとして、下記のようなファイルパスを表示するTextFieldと、
ファイルダイアログを表示するCommandButton を持つHBox を作成しようと思います。

Code:
{define-class public FileBox {inherits Frame}
  field tf:TextField
  field cb:CommandButton
  {constructor public {default ...}
    {construct-super.Frame {splice ...}}
    set self.tf = {TextField {splice ...}}
    set self.cb =
        {CommandButton
            label = "参照",
            {on Action do
                {if-non-null u = {choose-file} then
                    set self.tf.value = u.full-filename
                }
            }
        }
    {self.add {HBox self.tf, self.cb} }
  }
  {getter public {value}:String
    {return self.tf.value}
  }
}
{def fb = {FileBox width = 4in }}
{value fb}

現在は、残余引数をすべて親クラスの Frame のコンストラクタに渡しているので、
たとえば、vstretch? を指定すると TextField のコンストラクタでエラーになり、
editable? を指定すると、Frame のコンストラクタでエラーになります。
これを回避したいです。

つまり、FileBox のインスタンス作成時の引数として指定されたもののなかで、
HBox のオプションとして有効なものはHBoxに、
TextField のオプションとして有効なものはTextField のコンストラクタに渡したいです。

TextField、HBox それぞのオプションを明記し、それぞれ個別に指定するようなコーディングはしたくありません。
このようなことは可能でしょうか。




RE: 複合コントロールのコンストラクタ - nmyzk - 05-13-2013

こんな感じですか?

ClassType.get-optionで受け取れる引数をハンドリングして
それぞれのコンテンツに渡すイメージです。

渡すべきオプションや渡すべきでないオプションもあると思うので
その辺は適宜調整という感じで。
Code:
{curl 8.0 applet}{curl-file-attributes character-encoding = "utf8"}
{define-class public MultiControlField {inherits HBox}
  {constructor public {default                          ...                      } let (tf-args:Arguments,cb-args:Arguments,self-args:Arguments) = {self.separate-arguments {splice ...}}
    {construct-super {TextField {splice tf-args}}, {CommandButton {splice cb-args}}, {splice self-args}  }

  }
  {method private {separate-arguments                      ...                  }:(tf-args:Arguments,cb-args:Arguments,self-args:Arguments)

let tf-type:ClassType = TextField let cb-type:ClassType = CommandButton let self-type:ClassType = {type-of self} asa ClassType

     let (tf-args:Arguments,cb-args:Arguments,self-args:Arguments) = ({Arguments},{Arguments},{Arguments})

     ||///  ||1.何れか1つに振り分ける  ||/// {for (value:any,name:#String) in ... do
        {if-non-null name         then {if-non-null {tf-type.get-option name}             then {tf-args.append value,keyword = name} {continue} }

{if-non-null {cb-type.get-option name}             then {cb-args.append value,keyword = name} {continue} }

{if-non-null {self-type.get-option name} then {self-args.append value,keyword = name} }
         else {self-args.append value} }

    }
||++||///||++||2.引き受ける引数は全て振り分ける||++||///||++{for  (value:any,name:#String) in ... do||++||++    {if-non-null name||++     then||++        {if-non-null {tf-type.get-option name}||++         then||++            {tf-args.append value,keyword = name}||++        }||++||++        {if-non-null {cb-type.get-option name}||++         then||++            {cb-args.append value,keyword = name}||++        }||++||++||++ {self-args.append value,keyword = name}||++||++||++     else||++        {tf-args.append value}||++        {cb-args.append value}||++        {self-args.append value}||++    }||++||++||++}
    {return tf-args,cb-args,self-args}  }
}

{MultiControlField    editable? = false,    show-focus? = false}



RE: 複合コントロールのコンストラクタ - umemura - 05-15-2013

ありがとうございます。ClassType を使うとクラス個別の情報などを取得できて便利ですね。

ただ、これだと、CommandButton.label がうまくいきません。
オプション以外のアクセサやフィールドなどで、各クラスコンストラクタで個別に指定しているものは、
get-optionでは認識されないので、設定できないことが原因という認識です。

ClassType.get-setter を使って、インスタンス化した後に、セットする方法も考えてみます。