フレーム

概要

このセクションでは、Frame とその重要な2つのサブクラスである、ViewScrollBox について説明します。他に重要なサブクラスとして Dialog がありますが、それについては「ダイアログとコントロール」のセクションで説明しています。

フレーム

グラフィック階層を作成する際に、Box 内に複数のグラフィカル オブジェクトを収めるのは必ずしも必要ではなく、望ましくもありません。Frame クラスは、グラフィカル オブジェクトを 1 つだけ保持するコンテナを実装します。ただし、コンテナが保持するオブジェクト自体には複数のオブジェクを配置することができます。
Frame の簡単な用法には、グラフィカル オブジェクトの周りに作成するボーダーやマージンがあります。

例: Frame を使用してボーダーを作成
|| a Frame containing a VBox
{Frame
    width = 1.5cm,
    height = 1.5cm,
    background = "yellow",
    halign = "center",
    valign = "center",
    {VBox
        width = 1cm,
        height = 1cm,
        background = "lime"}
}
Frame には、width プロパティを持たないテキスト要素のコンテナとして使用するという方法もあります。テキスト要素の幅を設定するには、これを Frame に配置して Framewidth プロパティを設定します。

例: テキストを含む Frame の使用
{Table
    background = "beige",
    width = 14cm,
    {text
        color = "brown",
        font-size = 24pt,
        24-pt brown-colored text},
    {text
        color = "olive",
        font-size = 18pt,
        18-pt olive-colored text}
}

{Table
    background = "beige",
    width = 14cm,
    {Frame
        width = 5cm,
        {text
            color = "brown",
            font-size = 24pt,
            24-pt brown-colored text}},
    {Frame
        width = 3cm,
        {text
            color = "olive",
            font-size = 18pt,
            18-pt olive-colored text}}
}
同様に、コンテナ一杯に伸長するようなオブジェクトに Frame を使用してこれを固定サイズに抑えることができます。たとえば、OverlayBox に置かれたシェイプは、シェイプ自体で設定されたサイズとは関係なしに通常ボックス全体の端まで伸長します。次の例では、OverlayBox 内に置かれた 2 つの異なるサイズの RectangleGraphic が、Frame の内にそれぞれ収められていない場合はボックス一杯に伸長して一方が他方を隠してしまう様子を示しています。

例: Frame を使用したオブジェクトのサイズの固定
{OverlayBox
    width = 8cm,
    border-width = 1pt,
    border-color = "black",
    {RectangleGraphic
        width = 3cm,
        height = 3cm,
        fill-color = "yellow"
    },
    {RectangleGraphic
        width = 2cm,
        height = 1cm,
        fill-color = "blue"
    }
}

{OverlayBox
    width=8cm,
    {Frame
        {RectangleGraphic
            width = 3cm,
            height = 3cm,
            fill-color = "yellow"
        }
    },
    {Frame
        {RectangleGraphic
            width = 2cm,
            height = 1cm,
            fill-color = "blue"
        }
    }
}
       

ビュー

View はウィンドウを実装します。たとえば、Curl® 言語で書かれたアプレットを表示するブラウザ内のページや、別のウィンドウでポップアップ表示されるダイアログ ボックスは View です。View を作成すると、ホスト システムのウィンドウに自動的にアタッチされます。View で実行されるすべての操作はホスト システムの該当するウィンドウに直接転送されます。これには、View を閉じる操作や、移動または削除などが含まれます。View は通常、表示関連のグラフィック階層のルートで使用されます。View にはグラフィカル オブジェクトがネストたり、他の View オブジェクトが含まれるのが一般的です。
ViewFrame のサブクラスであり、グラフィカルな子を 1 つだけ含むことができます。1 つのグラフィカルな子に別のオブジェクトを指定して、これに複数のオブジェクトを含めることができます。VBox および HBoxView の子としてよく使用されます。また View には唯一のグラフィカルな子としてScrollBox を置くことができます。「スクロール ボックス」のセクションを参照してください。
View をもう 1 つの View が所有することもできます。View に所有された下位の View には、特定の結果がもたらされます。これは、View の親ビューが破棄されると他の View も自動的に破棄されるということです。View が所有されないようにするには、owner キーワード引数を null に設定します。
たとえば、ダイアログをポップアップする側の View は、そのダイアログの View の親になります。元の View が閉じて破棄されると、ダイアログにはこれ以上の役目はなくなり、同様に破棄されます。
View を作成すると、その FocusManager が作成されます。View には、それぞれキーボード イベントのディスパッチを管理する FocusManager があります。これには、Viewfocus-manager オプションからアクセスすることができます。フォーカス マネージャおよびキーボード イベントについての詳細は、「フォーカスとキー イベント」のセクションを参照してください。
View default コンストラクタにはさまざまなリスト引数があり、これらを使用して作成する View のタイプを指定することができます。引数はすべてキーワード引数で、既定値が提供されています。詳細については、API ドキュメンテーションを参照してください。
次の View メソッドを使用して、View を開いたり、非表示にしたり、閉じることができます。ディスプレイには通常複数の View があり、最上位の View が他の View の一部を隠蔽するようにスタックされている点に注目してください。
次の例のコマンドボタンを使用して表示を操作してください。View を閉じると、既定の動作ではそれを破棄します。破棄された ViewView.show または View.hide などのメソッドを呼び出すとエラーになります。このようなエラーを回避するために、この例では最初にオブジェクトの View.destroyed? プロパティをチェックしています。値が false の場合は、ビューの表示または非表示、移動、タイトルの変更が可能です。
注意: ビューを破棄したら、例を元に戻してから再度実行して新しいビューを表示して他のアクションを実行してください。

例: View の操作
{value
    let button-label:String = "Show"
    let move-count:int = 0
    let view:View = {View}
    let view-contents:VBox =
        {VBox
            margin = 5pt,
            {text
                color = {FillPattern.get-teal},
                See this view.
            }
        }
    {view.add view-contents}
    set view.title = "Original View"
    let no-more-view:TextFlowBox =
        {TextFlowBox
            {paragraph View already destroyed.},
            {paragraph No further operations possible.}
        }
    {spaced-hbox
        {CommandButton
            label = "Show",
            {on action:Action at b:CommandButton do
                {if not view.destroyed? then
                    {if button-label == "Show" then
                        || position the view
                        {view.set-position 4*72pt, 4*72pt}
                        || display the view
                        {view.show}
                        set button-label = "Hide"
                     else
                        || hide the view
                        {view.hide}
                        set button-label = "Show"
                    }
                    set b.label = button-label
                 else
                    {popup-message
                        no-more-view
                    }
                }
                {action.consume}
            }
        },
        {CommandButton
            label = "Move",
            {on action:Action do
                {if not view.destroyed? then
                    || move view back and forth
                    {if (move-count mod 2) == 0 then
                        {view.set-position 3*72pt, 2*72pt}
                     else
                        {view.set-position 2*72pt, 3*72pt}
                    }
                    {view-contents.add
                        {text
                            color = {FillPattern.get-red},
                            See view move.
                        }
                    }
                    set move-count = move-count + 1
                 else
                    {popup-message
                        no-more-view
                    }
                }
                {action.consume}
            }
        },

        {CommandButton
            label = "New Title",
            {on action:Action do
                {if not view.destroyed? then
                    || reset view's title
                    set view.title = "Retitled Window"
                 else
                    {popup-message
                        no-more-view
                    }
                    {action.consume}
                }
            }
        },

        {CommandButton
            label = "Close",
            {on action:Action do
                {if not view.destroyed? then
                    || close the view
                    {view.close}
                 else
                    {popup-message
                        no-more-view
                    }
                    {action.consume}
                }
            }
        }
    } || spaced-hbox
} || value
                                                                         
ビューはウィンドウを表し、ディスプレイに一度に複数のウィンドウを表示できることから、ディスプレイ上のビューのスタック順序を指定することができます。通常、ビューは 2 つのカテゴリとして最上位のビューと非最上位のビューに分類することができます。
最上位ビューはすべての非最上位ビューの上に浮かびます。View最上位に指定するには、View.set-topmost を呼び出して topmost?=true をその引数として与えます。ただし、複数の View を最上位として指定することができます。最上位ビューのカテゴリまたは非最上位ビューのカテゴリ内では、View.raise を呼び出して、View をカテゴリのスタックの上位に上げたり、View.lower を呼び出してView をのスタックの下位に下げることができます。最上位ビューを非最上位ビューに戻すには、View.set-topmost を呼び出して topmost?=false をその引数として指定します。
注意: ビューを破棄したら、例を元に戻してから再度実行して新しいビューを表示して他のアクションを実行してください。

例: View のスタック
{value
    let view:View =
        {View
            owner = null,
            {HBox
                margin = 10pt,
                color = "red",
                "the view"
            }
        }
    let msgtxt:String = "Revert example to get a new View"
    {spaced-hbox
        {CommandButton
            width = 1in,
            text-breakable? = true,
            label = "Show the View",
            {on action:Action do
                {if not view.destroyed? then
                    {view.show}
                 else
                    {popup-message msgtxt}
                }
                {action.consume}
            }
        },
        {CommandButton
            width = 1in,
            text-breakable? = true,
            label = "Send the View to the bottom",
            {on action:Action do
                {if not view.destroyed? then
                    {view.lower}
                 else
                    {popup-message msgtxt}
                }
                {action.consume}
            }
        },
        {CommandButton
            width = 1in,
            text-breakable? = true,
            label = "Raise the View to the top",
            {on action:Action do
                {if not view.destroyed? then
                    {view.raise}
                 else
                    {popup-message msgtxt}
                }
                {action.consume}
            }
        }
    }
}
       

スクロール ボックス

ScrollBox クラスはもう1つの Frame のサブクラスです。グラフィカル オブジェクトがコンテナに完全に収まらない場合、ScrollBox はコンテンツを圧縮せずに、水平または垂直スクロール バーを提供します。
次の例で、既定のオプション設定をすべて使用する ScrollBox を示します。

例: テキストを含む単純な ScrollBox
{ScrollBox
    width = 5cm,
    height = 3cm,
    {Frame
        width = 7cm,
        {text
            {paragraph
                The {monospace ScrollBox} class is used to
                contain a graphical object and provide
                horizontal and/or vertical scroll bars should
                the entire graphical object not fit entirely
                within the container.
            }
            {paragraph
                The {monospace ScrollBox} class is used to
                contain a graphical object and provide
                horizontal and/or vertical scroll bars should
                the entire graphical object not fit entirely
                within the container.
            }
            {paragraph
                Graphical options specific to the {monospace
                ScrollBox} include:
            }
        }
    }
}
次のセクションでは ScrollBox の動作や外観を変更するいくつかのプロパティを説明します。

スクロール バーのプロパティ

ScrollBox.hunitsizeScrollBox.vunitsize プロパティ、および ScrollBox.hblocksizeScrollBox.vblocksize プロパティは、ScrollBox によって提供された水平および垂直スクロール バーの単位とブロック サイズを指定します。これらのプロパティの既定値はすべて 0m で、これによりスクロール ボックスは ScrollBox とそのコンテンツの相対的なサイズの観点から動的に値を計算することができます。また、ScrollBox は、ScrollBoxとそのコンテンツの相対的なサイズの観点から両方のスクロール バーのScrollbar.thumb-length を計算することもできます。
ScrollBox.hscroll-quantized?ScrollBox.vscroll-quantized? プロパティは、水平および垂直スクロール バーの Scrollbar.quantized? の値を指定します。既定値は false で、コンテンツのあらゆるポイントにスクロールができます。値が true の場合は、スクロールがスクロール距離の単位の整数の倍数に制約されます。
次の例は、前述の例と似ていますが、hscroll-quantized?true に設定され、hscroll-quantized?false に設定されています。スペースを節約するために、この例、およびこのセクションのその他の例では、スクロール ボックスのコンテンツを作成するコードはサポート ファイルに移動されています。

例: 数量化されたスクロール
{ScrollBox
    width = 5cm,
    height = 3cm,
    hscroll-quantized? = true,
    {evaluate 
        {url "../../default/support/frame.scurl"}
    }
}    
ScrollBox.get-hscrollScrollBox.get-vscroll メソッドを使用して ScrollBox によって指定された Scrollbar コントロールへのアクセスを得ることができます。次の例では水平スクロール バーを取得し、その色を設定します。

例: Scrollbar プロパティの設定
{let sb:ScrollBox = 
    {ScrollBox
        width = 5cm,
        height = 3cm, 
        {evaluate 
            {url "../../default/support/frame.scurl"}
        }
    }
}
{let hbar:Scrollbar = {sb.get-hscroll}}
{set hbar.control-color = "teal"}
{set hbar.control-appearance-changeable? = true}
{value sb}
ScrollBox のプロパティを設定して、スクロール バーの外観を変更することも可能です。次の例ではスクロール ボックスに control-colorcontrol-appearance-changeable? プロパティを設定します。スクロール バーの効果に注目してください。Scrollbar コントロールの詳細については、「Scrollbar」を参照してください。

例: Scrollbar の外観の制御
{ScrollBox
    width = 5cm, height = 3cm,
    control-color = "teal", 
    control-appearance-changeable? = true,
    {evaluate 
        {url "../../default/support/frame.scurl"}
    }
}

スクロール バーの存在の制御

ScrollBox.hscroll?ScrollBox.vscroll? プロパティは ScrollBox で水平または垂直スクロール バーを使用するかどうかを指定します。既定では、どちらのプロパティの値も true で、どちらの方向のスクロール バーも使用できます。どちらかのプロパティの値が false に設定された場合は、その方向のスクロール バーは使用できず、ScrollBox はコンテンツを圧縮しようとします。
次の例では、水平スクロール バーのない ScrollBox を示しています。Frame とそのコンテンツの水平方向の寸法が圧縮されていることに注目してください。

例: 水平スクロール バーがない例
{ScrollBox
    width = 5cm, height = 3cm,
    hscroll? = false,
    {evaluate 
        {url "../../default/support/frame.scurl"}
    }
}
次の例では、垂直スクロール バーを削除します。この場合、テキスト コンテンツは読めなくなるので、垂直方向に圧縮されません。その代わり、コンテンツは垂直方向で省略されます。

例: 垂直スクロール バーがない例
{ScrollBox
    width = 5cm, height = 3cm,
    vscroll? = false,
    {evaluate 
        {url "../../default/support/frame.scurl"}
    }
}
この例において、スクロール ボックスは複数のグラフィック オブジェクトを含み、スクロール ボックスにすべてを一緒に収めることはできません。垂直方向のスクロールは無効で、水平スクロール バーを含むスクロール ボックスのコンテンツは使用可能なスペースに収まるよう無理に押し込められます。次の行をコメントアウトし、例を実行して、圧縮されない場合にグラフィック オブジェクトがどのように見えるかご覧ください。
vscroll? = false,

例: グラフィック コンテンツの垂直方向の圧縮
{let rect1:RectangleGraphic = 
    {RectangleGraphic width=3cm, height=1cm, fill-color="red"}
}
{let rect2:RectangleGraphic = 
    {RectangleGraphic width=2cm, height=2cm, fill-color="orange"}
}
{let rect3:RectangleGraphic = 
    {RectangleGraphic width=2cm, height=1cm, fill-color="lime"}
}
{let rect4:RectangleGraphic = 
    {RectangleGraphic width=2cm, fill-color="blue"}
}
{let rect5:RectangleGraphic = 
    {RectangleGraphic height=2cm, fill-color="purple"}
}
{let rect6:RectangleGraphic = 
    {RectangleGraphic width=4cm, height=5cm}
}
{ScrollBox
    width = 5cm,
    height = 3cm,
    vscroll? = false,
    {VBox
        {HBox
            rect1,
            rect2,
            rect3
        },
        {HBox
            rect4,
            rect5
        },
        rect6
    }
}
スクロール ボックスに水平および垂直スクロール バーが存在する場合、ScrollBox.shrink-hscroll?ScrollBox.shrink-vscroll? プロパティはスクロール バーを可視化するかどうかを制御します。既定値は true で、スクロール バーは必要のないときには縮んで見えなくなります。これらのプロパティを true に設定すると、それが不要なときは無効なスクロールバーとして表示されます。
次の例では、スクロール バーが縮まない ScrollBox を説明します。コマンド ボタンをクリックしてスクロール ボックスを含むビューを開いてください。ビューのサイズを変えることにより、スクロール バーを有効、または無効にできます。

例: スクロール バーを可視状態に保つ
{let frame:Frame = 
    {evaluate 
        {url "../../default/support/frame.scurl"}
    }
}   
{set frame.width = 10cm}
{CommandButton
    label = "Show ScrollBox",
    {on Action do
        let v:View = 
            {View 
                width = 3cm, 
                height = 3cm,
                {ScrollBox
                    shrink-vscroll? = false,
                    shrink-hscroll? = false,
                    frame
                }
            }
        {v.show}
    }
}
ScrollBox.always-disable-hscroll?ScrollBox.always-disable-vscroll? は必要とされるときにもスクロール バーを無効に見せます。規定値は false で、これは必要に応じてスクロール バーを有効にも無効にもします。ture に設定し、対応する shrink-* プロパティも true に設定すると、スクロール バーを不可視にレンダリングする間に ScrollBox のレイアウト調整が行われます。この組み合わせを使用して、使用可能なスペースの変更に伴ってコンテナがそれに含まれるコンテンツを圧縮することを回避できます。次の例では、Viewをどんなサイズに変えても Frame の幅とそれに含まれるテキストのレイアウトを維持します。

例: 不可視のスクロール バー
{let frame:Frame = 
    {evaluate 
        {url "../../default/support/frame.scurl"}
    }
}   
{set frame.width = 10cm}

{CommandButton
    label = "Show ScrollBox",
    {on Action do
        let v:View = 
            {View 
                {ScrollBox
                    always-disable-vscroll? = true,
                    always-disable-hscroll? = true,
                    frame
                }
            }
        {v.show}
    }
}
前の例と比較すると、この例では Frame のみを使用しています。ビューの幅がとても狭い場合、テキストのレイアウトが判読できなくなることを考慮する必要があります。

例: Frame 内のテキスト
{let frame:Frame = 
    {evaluate 
        {url "../../default/support/frame.scurl"}
    }
}   
{set frame.width = 10cm}
{CommandButton
    label = "Show Frame",
    {on Action do
        let v:View = 
            {View 
                frame
            }
        {v.show}
    }
}

ScrollBox 内の位置決め

ScrollBox はそれに含まれるコンテンツに対応してそれ自体の位置を決めるメソッドを提供します。メソッドには以下のものが含まれます。
ScrollBox.horizontal-positionScrollBox.vertical-position のプロパティはスクロール ボックスの位置を取得、または設定できます。
次の例では、ScrollBox.scroll-to-object を使用して指定された四角形の中にスクロール ボックスの位置を指定します。また、ScrollBox.horizontal-positionScrollBox.vertical-position を使用して新しい位置を返します。

例: ScrollBox の位置決め
{let rect1:RectangleGraphic = 
    {RectangleGraphic width=3cm, height=1cm, fill-color="red"}
}
{let rect2:RectangleGraphic = 
    {RectangleGraphic width=2cm, height=2cm, fill-color="orange"}
}
{let rect3:RectangleGraphic = 
    {RectangleGraphic width=2cm, height=1cm, fill-color="lime"}
}
{let rect4:RectangleGraphic = 
    {RectangleGraphic width=2cm, fill-color="blue"}
}
{let rect5:RectangleGraphic = 
    {RectangleGraphic height=2cm, fill-color="purple"}
}
{let rect6:RectangleGraphic = 
    {RectangleGraphic width=4cm, height=5cm}
}
{let sb:ScrollBox = 
    {ScrollBox
        width = 5cm,
        height = 3cm,
        {VBox
            {HBox
                rect1,
                rect2,
                rect3
            },
            {HBox
                rect4,
                rect5
            },
            rect6
        }
    }
}
{value 
    {VBox
        sb,
        {CommandButton
            label = "Scroll to Purple",
            {on Action do
                {sb.scroll-to-object rect5}
                {
                 popup-message 
                    {text 
                        Horizontal position: {value sb.horizontal-position}
                        {br}
                        Vertical position: {value sb.vertical-position}
                    }
                }
            }
        }
    }
}