TheSpecUIframework:Chapter 06

From 흡혈양파의 번역工房
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
창 관리하기

창 관리하기

이 책에서는 지금까지 ComposableModel 의 재사용에 대해 이야기하고, Spec의 기본적인 기능에 대해 논의했으며, 사용자 인터페이스의 위젯을 배치하는 방법을 제시했습니다. 아직 빠진 부분이 있는데, 작업중인 사용자 인터페이스에서 창 내부에 위젯을 모두 표시하는 것입니다. 지금까지의 예제에서는 창 관리를 위한 Spec의 몇 가지 기능은 살펴봤지만, 기본적으로 창을 여는 것을 제한했습니다.


이 장에서는 Spec을 사용하여 창을 관리하는 방법에 대한보다 완전한 개요를 제공합니다. 창의 열기와 닫기, 내장된 다이얼로그 박스 기능, 창 크기 조정 및 모든 종류의 창 장식을 보여줍니다.


실용 예제

실용 예제

사용이 가능한 창 환경설정 옵션을 설명하기 위해서, 두 개의 버튼이 나란히 배치 되어있는 간단한 "WindowExample"클래스를 사용합니다. 이 버튼들은 아직 어떤 행동과도 관련이 없으며, 필요한 내용은 이 장의 아래에있는 예제에서 추가될 것입니다.

ComposableModel subclass: #WindowExample
   instanceVariableNames: 'button1 button2'
   classVariableNames: ''
   package: 'Spec-BuildUIWithSpec'
WindowExample >> initializeWidgets
   button1 := self newButton.
   button2 := self newButton.
   button1 label: '+'.  button2 label: '-'.
WindowExample class >>defaultSpec
   ^ SpecRowLayout composed
         add: #button1; add: #button2; yourself.


창 또는 대화 상자 열기

사용자 인터페이스는 일반적(normal)인 창으로 열리거나 대화 상자로 열 수 있습니다. 즉 장식OkCancel 버튼이 포함되어 있다는 얘기입니다. 여기서는 대화 상자와 관련된 구성 옵션을 포함해서, 이 작업이 어떻게 수행되는지 보여줍니다.(창 장식에 대한 자세한 내용은 6.3 절을 참조하십시오)


창 열기

이전 섹션에서 살펴본 것처럼 사용자 인터페이스를 열려면, 해당 인터페이스의 ComposableModel 을 인스턴스화하고 openWithSpec 메시지를 보내야합니다. 이렇게 하면 사용자 인터페이스가 포함 된 WindowModel 의 인스턴스가 만들어지며 화면의 창에 표시됩니다.


우리는 이미 openWithSpec: 메서드, 특히 5 장에서 레이아웃 메시지의 이름을 인수로 사용하는 방법을 보았습니다. 기본 레이아웃을 사용하는 대신에(이 방법은 섹션 4.3 에 적혀 있습니다), 열려있는 UI 는 해당 메소드가 반환 한 레이아웃을 사용합니다.두 번째 변형은 SpecLayout 인스턴스(또는 그 하위 클래스의 인스턴스)를 사용하는 openWithSpecLayout: 입니다.


예를 들어 아래에서는 WindowExample 에 대해 창을 여는 세 가지 방법을 보여줍니다. 3 개의 동일한 창을 엽니다.

| we |
 we := WindowExample new.
 we openWithSpec.
 we openWithSpec: #defaultSpec.
 we openWithSpecLayout: we defaultSpec.


대화 상자 열기 및 설정 옵션

Spec 은 UI 를 OkCancel 버튼을 사용하는 간단한 대화 상자를 여는 쉬운 방법을 제공합니다. 이렇게 하려면 다음과 같이 openDialogWithSpec 메시지를 보내십시오.

| we diag |
 we := WindowExample new. 
 diag := we openDialogWithSpec.

이 결과(위 예제서는 diag 변수에 할당됨)는 DialogWindowModel 클래스(WindowModel 의 하위클래스)의 인스턴스가 됩니다. 편의상 openDialogWithSpec 은 메시지이름, 또는 SpecLayout 인스턴스로 특정 레이아웃을 인수로 가지는 openWindowWithSpec 과 동일한 변형을 가집니다.


DialogWindowModel 인스턴스(앞의 예제에서 diag)는 여러 가지 방법으로 구성할 수 있습니다. 사용자가 버튼을 클릭할 때 코드를 실행하려면, 인수 블록이 없는 okAction: 또는 cancelAction: 메시지를 보내면 됩니다. 블록이 "false"를 반환하면 창이 닫히지 않습니다(다른것이 반환되면 창은 닫힙니다). 이 창을 닫는 로직은 대화 상자 내용의 유효성 검사를 허용하며, 유효성 검사가 성공할 경우에만 닫히는것을 허용합니다.부연하자면, OK 버튼은 okButtonEnabled:false 메시지를 보내면 회색으로 표시되고, true 인수로 다시 활성화됩니다.


또한 Cancel 버튼을 클릭해서 상자를 닫으면 cancelled 메시지는 true 를 반환합니다.


전체 화면을 차지하기

마지막으로 UI 를 열어 Pharo 화면 전체를 관리 할 수도 있습니다. 다른 창은 없으며, UI 는 크기 조정이나 닫기 상자가 없는 전체 화면 또는 제목 표시 줄이 됩니다. 사실은 Pharo 전체 화면도 UI 창입니다.


Pharo 화면 전체를 가져 오려면 openWorldWithSpec 메시지를 보내십시오:

WindowExample new openWorldWithSpec.


Gnome3 notice header.png
halo 를 통해 UI 는 여전히 닫아질 수 있지만, 이전에 열려 있던 다른 창은 사라집니다.
Gnome3 notice footer.png


모달(modal) 창과 창 닫기

Windows 는 화면에 혼자있는 것이 아니며 영원히 존재할 수 있는것은 아닙니다. 여기서는 전체 사용자 인터페이스에 대한 완전한 제어권을 얻는 방법과 창을 닫는 로직에 연결하는 방법에 대해 설명합니다.


모달 창

모달 창은 전체 Pharo 사용자 인터페이스를 제어하는 ​​창으로, 열려있는 동안 다른 창을 선택할 수 없습니다. 이러한 특성은 대화 상자에 특히 유용하지만, 다른 종류의 창에도 필요한 경우는 있습니다.


Spec 은 열려있는 ComposableModel 에 해당하는 WindowModel 에 modalRelativeTo : World 라는 메시지를 보냄으로써, 모든 창을 모달로 만들 수 있습니다. WidowModel 에서 핸들을 얻으려면 window 메시지를 보냅니다(UI 가 openWithSpec 으로 열리는 경우).

| we |
 we := WindowExample new. 
 we openWithSpec.
 we window modalRelativeTo: World
Gnome3 notice header.png
modalRelativeTo: 의 인수는 항상 현재 표시된 위젯 계층의 루트(World)가 되어야 합니다.
Gnome3 notice footer.png


창 닫기 방지

Spec 은 사용자가 닫기 상자를 클릭 할 때 창을 효과적으로 닫을 수 있는지 확인하는 기능을 제공합니다. 이 기능을 사용하려면 먼저 askOkToClose: true 를 ComposableModel 에 보내서 해당되는 기능을 켜야합니다. 예를 들어 다음처럼 WindowExample 을 변경하면됩니다:

WindowExample >> initializeWidgets
   button1 := self newButton.
   button2 := self newButton.
   button1 label: '+'.
   button2 label: '-'.
   self askOkToClose: true.

그러나 이것만으로는 닫기 버튼의 동작은 변경되지 않으며, 계속 창을 닫을 수 있습니다. 이는 창을 닫을때 검사할 항목에 대한 구현 부분을 정의하지 않았기 때문입니다. 구현의 정의는, 아래처럼 ComposableModel 의 okToChange 메소드를 오버라이드 함으로써 쉽게 동작시킬 수 있습니다.


WindowExample >> okToChange
   ^false

이 메서드는 false 를 반환하기 때문에, 열려있는 WindowExample 윈도우의 닫기 버튼을 클릭해도 아무런 효과도 일어나지 않습니다. 이제 동작이 적용되는 창을 만들었습니다! 이 창을 닫으려면, 위 메서드의 구현을 true 를 반환하도록 변경해야 합니다(또는 코드를 지워도 되겠죠).


물론 앞의 okToChange 메서드 예제는 매우 단순하며 그리 유용한것도 아닙니다. 하지만 정말로 쓰려고 한다면, 창을 닫을때 검사 할 항목의 내용에 간단한 내용 대신에 어플리케이션에 관련된 로직(application-dependent logic)을 정의해야합니다. 시스템에는 참고할만한 okToChange 메소드의 예가 많이 있습니다.


창 닫기 지연

UI 의 WindowModel 에 whenClosedDo: 메시지를 보내서 창을 닫을 때마다 작업을 수행할 수도 있습니다. 예를 들어 다음의 예제에서는 UI 가 닫힐 때 전달할 작별 인사 메시지를 지정합니다.

| we |
 we := WindowExample new. 
 we openWithSpec.
 we window whenClosedDo: [ UIManager default inform: 'Bye bye!' ].


창 크기 및 장식

지금부터는, 창을 열기 전후에 창 크기를 조정 한 다음 창을 꾸미는 다른 컨트롤 위젯을 제거하는 방법에 대해 설명합니다.


초기 크기 설정 및 크기 변경

창이 열릴 때 창의 초기 크기를 설정하려면, 해당 ComposableModel 의 extent 메소드를 재정 의하여 Point 를 반환하거나, 인스턴스를 열기 전에 extent: 메시지를 보냅니다. 예를 들면 이렇습니다:

| we |
 we := WindowExample new.
 we extent: 300@80.
 we openWithSpec


창이 열린 이후라면, UI 의 창에 extent: 메시지를 보내 크기를 조정할 수도 있습니다. 예를 들어, 당신은 예제의 initializeWidgets 메서드를 변경하여 클릭한 버튼에 따라 윈도우의 크기가 자동 조절되도록 할 수 있습니다.

WindowExample >> initializeWidgets
  button1 := self newButton.
  button2 := self newButton.
  button1 label: '+'.
  button2 label: '-'.
  button1 action: [ self window extent: 500@200].
  button2 action: [ self window extent: 200@100].


고정 크기

창의 크기는 고정되어 사용자가 측면이나 모서리를 드래그하여 크기를 조정할 수 없습니다. 이것을 설정하기 위해서는 기본 위젯 라이브러리와 대화해야 합니다(Pharo 5 에서는 Morphic). 예제(WindowModel)의 Morphic 창을 얻고 다음과 같이 크기가 변경되지 않도록(unresizable) 지시합니다.

| wewin |
 wewin := WindowExample new openWithSpec.
 wewin window beUnresizeable


창 장식 제거하기

장식이 없는 창 (예 : 컨트롤 위젯이 없는 창)을 만드는 것이 의미있는 경우도 있습니다. 현재 이 구성은 해당 창의 ComposableModel 에서 수행 할 수는 없지만, 기본 위젯 라이브러리가 허용 할 수도 있습니다. 아래에서는 예제의 Morphic 창을 가져와서 다른 컨트롤 위젯을 제거하는 방법을 보여줍니다.

| wewin |
 wewin := WindowExample new openWithSpec.
 wewin window
    removeCollapseBox;
    removeExpandBox;
    removeCloseBox;
    removeMenuBox
Gnome3 notice header.png
이 윈도우는 여전히 halo 메뉴를 사용하거나, WindowModel 인스턴스(에제의 wewin)에서 close 를 호출하여 닫을 수 있습니다.
Gnome3 notice footer.png


최종 세부 정보 : 제목, 아이콘 및 텍스트 정보

창에 대한 제목과 텍스트를 제공함으로써 window 에 대한 텍스트 정보를 제공 할 수 있습니다.


제목 설정 및 변경

기본적으로 새 창의 제목은 Untitled window 입니다. 이것은 title 메소드(ComposableModel 의 메서드)를 오버라이딩하고 제목으로 사용될 문자열을 리턴함으로써 변경될 수 있습니다. 예를 들어 다음처럼 예제 사용자 인터페이스의 제목을 지정할 수 있습니다:

WindowExample >> title
   ^ 'Click to grow or shrink.'


또한 (title 메소드를 지정하거나)새로운 제목의 title: 메시지를 인수로 UI 창에 보내서 UI 를 열면, 해당 제목을 설정할 수 있습니다. 예제는 아래와 같습니다:

| we |
 we := WindowExample new. 
 we openWithSpec.
 we window title: 'I am different!'


아이콘 설정하기

Pharo 메인창 하단에는 윈도우 작업 표시 줄이 있어서, 사용자가 각 창을 나타내는 버튼을 클릭하여 창 사이를 전환 할 수 있습니다. 이 창을 나타내는 버튼에는 윈도우의 종류를 나타내는 아이콘도 표시되고 있습니다. 이 아이콘은 Spec 을 통해 두 가지 다른 방법으로 구성 할 수 있습니다.


첫째, windowIcon: 메시지를 ComposableModel 에 보내면 아래 그림과 같이 각 창마다 아이콘을 설정할 수 있습니다. 창을 열기 전이나 후에 언제 메시지를 보내도 상관 없습니다.

| wm1 wm2 |
 wm1 := WindowExample new.
 wm1 openWithSpec.
 wm1 windowIcon: (Smalltalk ui icons iconNamed: #thumbsDown).
 wm2 := WindowExample new.
 wm2 windowIcon: (Smalltalk ui icons iconNamed: #thumbsUp).
 wm2 openWithSpec.


두 번째 방법으로, 아이콘은 아래와 같이 "windowIcon"메시지를 재정 의하여 변경할 수 있습니다. 아래의 코드는 Pharo 6 를 위한 것입니다. Pharo 5 에서 작동시키려면 self iconNamed: 를 Smalltalk ui icons iconNamed: 변경해 주시기 바랍니다.

WindowExample >> windowIcon
   ^ self iconNamed: #thumbsUp


Gnome3 notice header.png
windowIcon 메서드를 변경하면 작업 표시 줄이 주기적으로 새로 고쳐지기 때문에 열려있는 모든 창에 영향을 줍니다. 이 갱신 방식은 windowIcon: 을 창을 열기 전이나 후에 보낼 수 있는 이유가 되기도 합니다.
Gnome3 notice footer.png


about 텍스트 설정하기

윈도우의 텍스트를 설정하려면, 해당 ComposableModel 의 aboutText 메소드를 오버라이드해서 새로운 about 텍스트를 반환할 수도 있습니다. 예를 들어, 열기 전에 인스턴스에 aboutText: 메시지를 보내십시오.

| we |
 we := WindowExample new.
 we aboutText: 'Click + to grow, - to shrink.'.
 we openWithSpec


결론

이 장에서는 Windows 와 관련이있는 Spec 의 기능을 다루었습니다. 먼저 창의 열기 및 닫기와 창을 대화 상자로 여는 방법에 대해 이야기 했습니다. 그 다음 창 크기와 장식 위젯을 구성했습니다. 그리고 창에 대한 작지만 중요한 세부 사항(창제목,아이콘,텍스트)으로 이 장을 끝냈습니다.


Notes