# Switch (JavaScript)

Taryn Fox
jewelfox@fursona.net 2012
켬/끔 상태를 뒤집을 수 있는 슬라이딩 스위치
조성호
shcho@gnome.org 2017-2019.

# Switch

스위치 위치는 켬과 끔이 있습니다. 이 예제에서는 어떤 Image를 창에 보여줄 지 여러 스위치로 동시에 제어하는 방법을 보여드립니다. 이 예제에서 사용한 그림은 여기에서 다운로드할 수 있습니다.

redfox.png, muteswan.png, fruitbat.png, gentoopenguin.png 파일이 동일한 디렉터리에 없으면 창에는 그림 대신 "깨진 그림" 아이콘이 나타납니다. 원하는 대로 코드와 그림 이곳저곳을 바꿀 수 있지만 이 예제에서 크리에이티브 커먼즈 라이선스 기반으로 활용하는 사진은 다음 원본을 가져왔으며 640x425 크기로 잘랐습니다:

Rob Lee의 Red fox photo는 CC-By 라이선스를 따릅니다

Ken Funakoshi의 Gentoo penguin photo는 CC-By-SA 라이선스를 따릅니다

Shek Graham의 Fruit bat photo는 CC-By 라이선스를 따릅니다

Mindaugas Urbonas의 Mute swan photo는 CC-By-SA 라이선스를 따릅니다

그놈 사진의 제작자와 라이선스 정보는 프로그램의 AboutDialog로 나타냅니다. 항상 크리에이티브 커먼즈 라이선스 작품을 사용할 때 원 저작자 저작 정보 기입을 기억하십시오!

# 가져올 라이브러리

#!/usr/bin/gjs

const Gio = imports.gi.Gio; const Gtk = imports.gi.Gtk; const Lang = imports.lang;

이 프로그램을 실행할 때 가져올 라이브러리입니다. 시작 부분에 항상 gjs가 필요함을 알리는 줄을 작성해야 함을 기억하십시오.

# 프로그램 창 만들기

const SwitchExample = new Lang.Class({ Name: 'Switch Example',

// Create the application itself _init: function() { this.application = new Gtk.Application({ application_id: 'org.example.jsswitch', flags: Gio.ApplicationFlags.FLAGS_NONE });

// Connect 'activate' and 'startup' signals to the callback functions this.application.connect('activate', Lang.bind(this, this._onActivate)); this.application.connect('startup', Lang.bind(this, this._onStartup)); },

// Callback function for 'activate' signal presents window when active _onActivate: function() { this._window.present(); },

// Callback function for 'startup' signal creates the menu and builds the UI _onStartup: function() { this._initMenus(); this._buildUI (); },

이 예제의 모든 코드는 SwitchExample 클래스에 들어갔습니다. 위 코드는 위젯과 창이 들어가는 Gtk.Application을 만듭니다.

창을 만들고 위젯을 그 안에 넣으려 _buildUI를 호출할 수 있기 전, 그놈에 메뉴를 만들어주라고 지시하는 _initMenus를 호출해야합니다. _onStartup에서 _initMenus를 우선 호출하는 동안 어떤 순서로 두는지는 중요하지 않으니, _buildUI 코드 다음에 _initMenus의 실제 코드를 둘 수 있습니다.

// Build the application's UI _buildUI: function() {

// Create the application window this._window = new Gtk.ApplicationWindow({ application: this.application, window_position: Gtk.WindowPosition.CENTER, border_width: 20, title: "Animal Creator"});

_buildUI 함수는 프로그램 사용자 인터페이스를 만드는 모든 코드를 넣는 곳입니다. 첫 단계에서는 모든 위젯을 우겨넣을 새 Gtk.ApplicationWindow를 만듭니다.

# 스위치 만들기

// Create the image widget and set its default picture this._image = new Gtk.Image ({file: "redfox.png"});

우선 스위치가 제어할 Image를 만들겠습니다. 이 프로그램과 동일한 디렉터리에 redfox.png 그림을 두어야 함을 기억하십시오.

// Create a label for the first switch this._flyLabel = new Gtk.Label ({ label: "Make it fly", margin_right: 30});

// Create the first switch and set its default position this._flySwitch = new Gtk.Switch ({active: false}); this._flySwitch.connect ('notify::active', Lang.bind (this, this._switchFlip));

// Create a label for the second switch this._birdLabel = new Gtk.Label ({ label: "Make it a bird", margin_right: 30});

// Create the second switch this._birdSwitch = new Gtk.Switch ({active: false}); this._birdSwitch.connect ('notify::active', Lang.bind (this, this._switchFlip));

각 스위치에 표시할 Label을 만들고 우측에 약간의 여백을 주어 스위치 뒤에서 쑤셔 넣은 느낌이 안나게 하겠습니다. 그 다음 스위치를 만들고 기본적으로 스위치를 꺼둔 상태로 설정하겠습니다.

스위치를 다른 방향으로 제낄 경우 스위치에서 내보내는 시그널은 notify::active입니다. 스위치를 만들고 나면 notify::active 시그널을 _switchFlip 함수에 연결합니다. 여러 스위치가 서로 다른 동작을 한다면 다른 함수에 연결해야 합니다만, 이 스위치는 _image로 표시한 그림을 처리하는 동일한 동작을 하는데 씁니다.

// Create a grid for the labels and switches beneath the picture this._UIGrid = new Gtk.Grid ({ halign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER, margin_top: 20});

// Attach the labels and switches to that grid this._UIGrid.attach (this._flyLabel, 0, 0, 1, 1); this._UIGrid.attach (this._flySwitch, 1, 0, 1, 1); this._UIGrid.attach (this._birdLabel, 0, 1, 1, 1); this._UIGrid.attach (this._birdSwitch, 1, 1, 1, 1);

// Create a master grid to put both the UI and the picture into this._mainGrid = new Gtk.Grid ({ halign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER });

// Attach the picture and the UI grid to the master grid this._mainGrid.attach (this._image, 0, 0, 1, 1); this._mainGrid.attach (this._UIGrid, 0, 1, 1, 1);

레이블과 스위치를 넣을 Grid를 먼저 만들어, 그림 사이에 간격을 준 2x2 배치로 모아둘 수 있습니다. 그 다음 더 큰 2x1 그리드를 활용하여 상단에 그림을 넣도록 하고 레이블과 스위치는 하단에 넣도록 합니다.

// Add the master grid to the window this._window.add (this._mainGrid);

// Show the window and all child widgets this._window.show_all(); },

마지막으로 창에 제일 큰 그리드를 추가하고, 창에서 창 자신과 그 안에 들어간 위젯을 모두 보여주도록 하겠습니다.

# 스위치 전환을 처리하는 함수

_switchFlip: function() {

// Change the picture depending on which switches are flipped if (this._flySwitch.get_active()) {

if (this._birdSwitch.get_active()) this._image.set_from_file ("muteswan.png");

else this._image.set_from_file ("fruitbat.png"); }

else {

if (this._birdSwitch.get_active()) this._image.set_from_file ("gentoopenguin.png");

else this._image.set_from_file ("redfox.png");

}

},

스위치를 제낄 때마다, 이 함수는 두 스위치 중 어떤 스위치가 동작했는지 스위치 내장 get_active() 함수로 나중에 확인합니다. 그 다음 그림을 바로 바꿉니다. 이미 그림이 있다 하더라도 원하는 대로 그림을 바꿀 수 있습니다.

# AboutDialog 만들기

_initMenus: function() {

// Build the application's menu so we can have an "About" button let menu = new Gio.Menu(); menu.append("About", 'app.about'); menu.append("Quit",'app.quit'); this.application.set_app_menu(menu);

// Bind the "About" button to the _showAbout() function let aboutAction = new Gio.SimpleAction ({ name: 'about' }); aboutAction.connect('activate', Lang.bind(this, function() { this._showAbout(); })); this.application.add_action(aboutAction);

// Bind the "Quit" button to the function that closes the window let quitAction = new Gio.SimpleAction ({ name: 'quit' }); quitAction.connect('activate', Lang.bind(this, function() { this._window.destroy(); })); this.application.add_action(quitAction); },

첫 단계에서는 "정보" 단추를 넣을 GMenu를 만듭니다. 화면의 좌측 상단 구석에 뜰 프로그램 이름을 눌렀을 떄 현재 활동 옆에 나타나는 메뉴입니다. 우리가 만든 메뉴에는 정보, 끝내기 옵션 두개를 넣습니다.

_showAbout: function () {

// String arrays of the names of the people involved in the project var artists = ['Rob Lee http://en.wikipedia.org/wiki/File:Fuzzy_Freddy.jpg', 'Ken Funakoshi http://en.wikipedia.org/wiki/File:Pygoscelis_papua_-Nagasaki_Penguin_Aquarium_-swimming_underwater-8a.jpg', 'Shek Graham http://www.flickr.com/photos/shekgraham/127431519/in/photostream/', 'Mindaugas Urbonas http://commons.wikimedia.org/wiki/File:Mute_Swan-Mindaugas_Urbonas.jpg']; var authors = ["GNOME Documentation Team"]; var documenters = ["GNOME Documentation Team"];

// Create the About dialog let aboutDialog = new Gtk.AboutDialog({ title: "AboutDialog Example", program_name: "Animal Creator", copyright: "Copyright \xa9 2012 GNOME Documentation Team\n\nRed fox photo licensed CC-By by Rob Lee\nGentoo penguin photo licensed CC-By-SA by Ken Funakoshi\nFruit bat photo licensed CC-By by Shek Graham\nMute swan photo licensed CC-By-SA by Mindaugas Urbonas\nLinks to the originals are available under Credits.\n\nHave you hugged a penguin today?", artists: artists, authors: authors, documenters: documenters, website: "http://developer.gnome.org", website_label: "GNOME Developer Website" });

// Attach the About dialog to the window aboutDialog.modal = true; aboutDialog.transient_for = this._window;

// Show the About dialog aboutDialog.show();

// Connect the Close button to the destroy signal for the dialog aboutDialog.connect('response', function() { aboutDialog.destroy(); }); }

});

AboutDialog에는 여러분이 설정할 수 있는 여러 다른 요소가 있는데, 프로그램을 만들 때 기여한 모든 사람, 그리고 이 부분을 봐야 할 독자에게 보여줄 참고 내용을 담습니다. 이 경우 저작권 섹션에 참고 메모와 만든 사람의 사진 원본 촬영자 목록을 올려둡니다. 다만, 아티스트 섹션에는 만든 사람 단추를 눌렀을 때 원본 사진 링크와 사진사 목록을 보여줍니다. 웹 URL은 만든 사람 섹션에서 누를 수 있는 항목으로 이름에 걸어두겠습니다.

// Run the application let app = new SwitchExample (); app.application.run (ARGV);

마지막으로, 마무리한 SwitchExample 클래스의 새 인스턴스를 만들고, 프로그램 실행을 설정합니다.

# 완전한 코드 예제

#!/usr/bin/gjs

imports.gi.versions.Gtk = '3.0';

const Gio = imports.gi.Gio; const Gtk = imports.gi.Gtk;

class SwitchExample {

// Create the application itself constructor() { this.application = new Gtk.Application({ application_id: 'org.example.jsswitch' });

// Connect 'activate' and 'startup' signals to the callback functions this.application.connect('activate', this._onActivate.bind(this)); this.application.connect('startup', this._onStartup.bind(this)); }

// Callback function for 'activate' signal presents window when active _onActivate() { this._window.present(); }

// Callback function for 'startup' signal creates the menu and builds the UI _onStartup() { this._initMenus(); this._buildUI(); }

// Build the application's UI _buildUI() {

// Create the application window this._window = new Gtk.ApplicationWindow({ application: this.application, window_position: Gtk.WindowPosition.CENTER, border_width: 20, title: "Animal Creator"});

// Create the image widget and set its default picture this._image = new Gtk.Image ({file: "redfox.png"});

// Create a label for the first switch this._flyLabel = new Gtk.Label ({ label: "Make it fly", margin_right: 30});

// Create the first switch and set its default position this._flySwitch = new Gtk.Switch ({active: false}); this._flySwitch.connect ('notify::active', this._switchFlip.bind(this));

// Create a label for the second switch this._birdLabel = new Gtk.Label ({ label: "Make it a bird", margin_right: 30});

// Create the second switch this._birdSwitch = new Gtk.Switch ({active: false}); this._birdSwitch.connect ('notify::active', this._switchFlip.bind(this));

// Create a grid for the labels and switches beneath the picture this._UIGrid = new Gtk.Grid ({ halign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER, margin_top: 20});

// Attach the labels and switches to that grid this._UIGrid.attach (this._flyLabel, 0, 0, 1, 1); this._UIGrid.attach (this._flySwitch, 1, 0, 1, 1); this._UIGrid.attach (this._birdLabel, 0, 1, 1, 1); this._UIGrid.attach (this._birdSwitch, 1, 1, 1, 1);

// Create a master grid to put both the UI and the picture into this._mainGrid = new Gtk.Grid ({ halign: Gtk.Align.CENTER, valign: Gtk.Align.CENTER });

// Attach the picture and the UI grid to the master grid this._mainGrid.attach (this._image, 0, 0, 1, 1); this._mainGrid.attach (this._UIGrid, 0, 1, 1, 1);

// Add the master grid to the window this._window.add (this._mainGrid);

// Show the window and all child widgets this._window.show_all(); }

_switchFlip() {

// Change the picture depending on which switches are flipped if (this._flySwitch.get_active()) {

if (this._birdSwitch.get_active()) this._image.set_from_file ("muteswan.png"); else this._image.set_from_file ("fruitbat.png"); } else {

if (this._birdSwitch.get_active()) this._image.set_from_file ("gentoopenguin.png"); else this._image.set_from_file ("redfox.png"); } }

_initMenus() {

// Build the application's menu so we can have an "About" button let menu = new Gio.Menu(); menu.append("About", 'app.about'); menu.append("Quit",'app.quit'); this.application.set_app_menu(menu);

// Bind the "About" button to the _showAbout() function let aboutAction = new Gio.SimpleAction ({ name: 'about' }); aboutAction.connect('activate', () => { this._showAbout(); }); this.application.add_action(aboutAction);

// Bind the "Quit" button to the function that closes the window let quitAction = new Gio.SimpleAction ({ name: 'quit' }); quitAction.connect('activate', () => { this._window.destroy(); }); this.application.add_action(quitAction); }

_showAbout() {

// String arrays of the names of the people involved in the project var artists = ['Rob Lee http://en.wikipedia.org/wiki/File:Fuzzy_Freddy.png', 'Ken Funakoshi http://en.wikipedia.org/wiki/File:Pygoscelis_papua_-Nagasaki_Penguin_Aquarium_-swimming_underwater-8a.png', 'Shek Graham http://www.flickr.com/photos/shekgraham/127431519/in/photostream/', 'Mindaugas Urbonas http://commons.wikimedia.org/wiki/File:Mute_Swan-Mindaugas_Urbonas.png']; var authors = ["GNOME Documentation Team"]; var documenters = ["GNOME Documentation Team"];

// Create the About dialog let aboutDialog = new Gtk.AboutDialog({ title: "AboutDialog Example", program_name: "Animal Creator", copyright: "Copyright \xa9 2012 GNOME Documentation Team\n\nRed fox photo licensed CC-By by Rob Lee\nGentoo penguin photo licensed CC-By-SA by Ken Funakoshi\nFruit bat photo licensed CC-By by Shek Graham\nMute swan photo licensed CC-By-SA by Mindaugas Urbonas\nLinks to the originals are available under Credits.\n\nHave you hugged a penguin today?", artists: artists, authors: authors, documenters: documenters, website: "http://developer.gnome.org", website_label: "GNOME Developer Website" });

// Attach the About dialog to the window aboutDialog.modal = true; aboutDialog.transient_for = this._window;

// Show the About dialog aboutDialog.show();

// Connect the Close button to the destroy signal for the dialog aboutDialog.connect('response', function() { aboutDialog.destroy(); }); } };

// Run the application let app = new SwitchExample (); app.application.run (ARGV);

# 자세한 문서

GMenu

GSimpleAction

Gtk.Application

Gtk.ApplicationWindow

Gtk.Grid

Gtk.Image

Gtk.Label

Gtk.Switch