<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" type="topic" id="image-viewer.c" lang="ko">

  <info>
    <title type="text">그림 보기(C)</title>
    <link type="guide" xref="c#examples"/>

    <desc>간단한 "Hello world" Gtk 프로그램에 약간의 무언가가 더 들어갑니다.</desc>

    <revision pkgversion="0.1" version="0.1" date="2011-03-18" status="review"/>
    <credit type="author">
      <name>그놈 문서 프로젝트</name>
      <email its:translate="no">gnome-doc-list@gnome.org</email>
    </credit>
    <credit type="author">
      <name>Johannes Schmid</name>
      <email its:translate="no">jhs@gnome.org</email>
    </credit>
    <credit type="editor">
      <name>Marta Maria Casetti</name>
      <email its:translate="no">mmcasetti@gmail.com</email>
      <years>2013</years>
    </credit>
  <credit type="translator copyright"><name>조성호</name><email>shcho@gnome.org</email><years>2017-2019.</years></credit></info>

<title>그림 보기</title>

<synopsis>
  <p>이 지침서를 통해 다음을 배웁니다:</p>
  <list>
    <item><p>C/GObject 프로그래밍 일부 기본 개념</p></item>
    <item><p>C 언어로 Gtk 프로그램을 작성하는 방법</p></item>
  </list>
</synopsis>

<media type="image" mime="image/png" src="media/image-viewer.png"/>

<section id="anjuta">
  <title>안주타에서 프로젝트 만들기</title>
  <p>코딩을 시작하기 전에 안주타에서 새 프로젝트를 설정해야합니다. 이 프로그램은 빌드에 필요한 모든 파일을 만들고 그 다음 코드를 실행합니다. 또한 이 모든 상태를 유지 관리하는데 쓸만합니다.</p>
  <steps>
    <item>
    <p>안주타를 시작하고 <guiseq><gui>파일</gui><gui>새로 만들기</gui><gui>프로젝트</gui></guiseq> 를 눌러 프로젝트 마법사를 여십시오.</p>
    </item>
    <item>
    <p><gui>C</gui> 탭에서 <gui>GTK+ (단순)</gui>를 선택하고, <gui>계속</gui>을 누른 다음, 나타난 페이지에서 몇가지 자세한 내용을 입력하십시오. 프로젝트 이름과 디렉터리에 <file>image-viewer</file>를 입력하십시오.</p>
   	</item>
    <item>
    <p>앞서 따라하기 지침을 통해 사용자 인터페이스를 직접 만들 예정이므로 <gui>사용자 인터페이스에 GtkBuilder 사용</gui> 설정을 껐는지 확인하십시오. 인터페이스 빌더 사용법을 알아보려면 <link xref="guitar-tuner.c">기타 조율 프로그램</link> 따라하기 지침서를 확인하십시오.</p>
    </item>
    <item>
    <p><gui>적용</gui>을 누르면 프로젝트를 만들어줍니다. <gui>프로젝트</gui>나 <gui>파일</gui>탭에서 <file>src/main.c</file> 파일을 여십시오. 다음 줄로 시작하는 일부 코드를 볼 수 있어야합니다:</p>
    <code mime="text/x-csrc">
#include &lt;config.h&gt;
#include &lt;gtk/gtk.h&gt;</code>
    </item>
  </steps>
</section>

<section id="build">
  <title>첫 코드 작성</title>
  <p>C는 장황하게 하나하나 다 따지고 들어가야 하는 언어니, 좀 많은 코드가 들어가 있는 파일에 놀라지 않으셔도 됩니다. 대부분은 서식 코드입니다. 이 코드에서는 (빈) 창을 불러와 열고 화면에 나타냅니다. 자세한 내용은 아래에 있습니다. 기본을 이미 알고 있다면 이 부분은 건너뛰십시오:</p>

  <list>
  <item>
    <p>상단의 <code>#include</code> 세 줄은 <code>config</code>(쓸만한 autoconf 빌드 정의),  <code>gtk</code>(사용자 인터페이스), <code>gi18n</code>(국제화) 라이브러리입니다. 이 라이브러리의 함수를 나머지 코드에서 사용하겠습니다.</p>
   </item>
   <item>
    <p><code>create_window</code> 함수는 (비어있는) 새 창을 만들고 창을 닫을 때 프로그램을 빠져나갈 시그널을 연결합니다.</p>
    <p>시그널 연결은 단추를 누르거나 어떤 동작을 취할 때 처리할 일을 정의하는 방식입니다. 여기서 창을 닫을 때 <code>destroy</code> 함수를 호출(하고 앱을 끝내기)합니다.</p>
   </item>
   <item>
    <p><code>main</code> 함수는 C 프로그램을 시작할 때 기본으로 실행하는 함수입니다. 이 함수에서 몇가지 함수를 호출하여 설정하고 프로그램을 실행합니다. <code>gtk_main</code> 함수는 사용자 인터페이스를 실행하고 사용자 반응(마우스 단추 누름, 키보드 키 누름)대기를 시작하는 GTK 메인 루프 시작 함수입니다.</p>
   </item>
   <item>
    <p><code>ENABLE_NLS</code> 상태 정의는 프로그램을 번역하는 프레임워크 <code>gettext</code>를 설정합니다. 이 함수는 프로그램을 실행할 때 번역 도구가 프로그램을 어떻게 다뤄야 하는지를 설정합니다.</p>
   </item>
  </list>

  <p>이 코드를 사용할 준비가 됐으니 <guiseq><gui>빌드</gui><gui>프로젝트 빌드</gui></guiseq>(또는 <keyseq><key>Shift</key><key>F7</key></keyseq> 키 누름)를 눌러 코드를 컴파일할 수 있습니다.</p>
  <p>디버깅 빌드 설정이 나타나는 다음 창에서 <gui>실행</gui> 을 누르십시오. 처음 빌드할 때 한번만 하면 됩니다.</p>
</section>

<section id="ui">
<title>사용자 인터페이스 만들기</title>
<p>이제 비어있는 창에 숨결을 불어넣겠습니다. GTK는 다른 위젯을 넣을 수 있고 다른 컨테이너도 넣을 수 있는 <code>GtkContainer</code>로  사용자 인터페이스를 모아둡니다. 여기서는 여러가지 컨테이너 중 가장 간단한 <code>GtkBox</code>를 사용하겠습니다:</p>
<code mime="text/x-csrc">
static GtkWidget*
create_window (void)
{
	GtkWidget *window;
	GtkWidget *button;
	GtkWidget *image;
	GtkWidget *box;

	/* Set up the UI */
	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
	gtk_window_set_title (GTK_WINDOW (window), "image-viewer-c");

	box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
	button = gtk_button_new_with_label (_("Open image"));
	image = gtk_image_new ();

	gtk_box_pack_start (GTK_BOX (box), image, TRUE, TRUE, 0);
	gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);

	gtk_container_add (GTK_CONTAINER (window), box);

	/* Connect signals */

	/* Show open dialog when opening a file */
	g_signal_connect (button, "clicked", G_CALLBACK (on_open_image), image);

	/* Exit when the window is closed */
	g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);

	return window;
}
</code>
  <steps>
    <item>
    <p>첫 줄은 우리가 쓰려는 그림을 여는 단추, 그림 보기 위젯 그 자체, 컨테이너로 쓸 박스 위젯을 만듭니다. <code>GTK_BOX</code> 같은 매크로는 동적 자료형 검사와 객체지향을 지원하지 않는 C 언어에서 특별하게 캐스팅할 목적으로 사용합니다.</p>
    </item>
    <item>
    <p><code>gtk_box_pack_start</code> 호출로 박스에 두 위젯을 추가하고 동작을 정의합니다. 그림은 활용 가능한 공간만큼 충분히 확장하고, 단추는 필요한 만큼만 커집니다. 위젯의 크기를 분명하게 설정하지 않음을 알아채셨을 겁니다. GTK에서는 창 크기가 달라져도 보기 좋은 배치를 쉽게하기에 직접 설정할 필요가 없습니다. 이 과정이 끝나면 박스를 창에 추가합니다.</p>
    </item>
    <item>
    <p>단추를 사용자가 눌렀을 때 어떤 일이 일어날 지 정해야합니다. GTK는 <em>시그널</em> 개념을 활용합니다. 단추를 누르면, 어떤 동작과 연결할 수 있는 <em>clicked</em> 시그널을 방출합니다. 사용자가 단추를 누르면  <code>on_image_open</code> 함수를 호출하여 그림을 이 함수의 인자로 전달하라고 GTK에 지시할 때 <code>g_signal_connect</code> 함수를 사용하면 됩니다. 다음 섹션에서 <em>콜백</em>을 정의하겠습니디.</p>
    </item>
    <item>
    <p>마지막 <code>g_signal_connect()</code> 함수에서는 창을 닫을 때 프로그램을 빠져나갈지를 확인합니다.</p>
    </item>
    <item>
    <p>마지막 단계에서는 창과 창이 담고 있는 모든 위젯을 보여줄 <code>main()</code> 함수의 <code>gtk_widget_show</code> 호출을<code>gtk_widget_show_all()</code> 함수로 바꾸었는지 확인하십시오.</p>
    </item>
  </steps>
</section>

<section id="image">
<title>그림 표시</title>
<p><em>clicked</em> 시그널이나 위에서 전에 언급한 단추의 시그널 핸들러를 정의하겠습니다. <code>create_window()</code> 메서드 전에 이 코드를 추가하십시오.</p>
<code mime="text/x-csrc">
static void
on_open_image (GtkButton* button, gpointer user_data)
{
	GtkWidget *image = GTK_WIDGET (user_data);
	GtkWidget *toplevel = gtk_widget_get_toplevel (image);
	GtkFileFilter *filter = gtk_file_filter_new ();
	GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Open image"),
	                                                 GTK_WINDOW (toplevel),
	                                                 GTK_FILE_CHOOSER_ACTION_OPEN,
	                                                 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
	                                                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
	                                                 NULL);

	gtk_file_filter_add_pixbuf_formats (filter);
	gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog),
	                             filter);

	switch (gtk_dialog_run (GTK_DIALOG (dialog)))
	{
		case GTK_RESPONSE_ACCEPT:
		{
			gchar *filename =
				gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
			gtk_image_set_from_file (GTK_IMAGE (image), filename);
			break;
		}
		default:
			break;
	}
	gtk_widget_destroy (dialog);
}
</code>
  <p>지금까지 우리가 다루어왔던 어떤 코드보다 조금 복잡하니 하나씩 뜯어보도록 하겠습니다:</p>
  <list>
    <item><p>시그널의 첫 인자는 언제나 시그널로 보낼 위젯입니다. 때로는 시그널과 관련된 다른 인자가 오기도 하지만, <em>clicked</em> 시그널은 그렇지 않습니다. 그 다음은 시그널을 연결할 때 우리가 넘길 데이터를 가리키는 <code>user_data</code> 포인터 인자입니다. 이 경우 <code>GtkImage</code> 객체입니다.</p>
    </item>
    <item>
      <p>다음 관심을 가질 부분에서는 <code>gtk_file_chooser_dialog_new</code>를 사용하여 선택한 파일을 만드는 대화상자입니다. 함수에서는 대화상자 제목, 대화상자의 상위 창, 여러 단추에 관련된 값 같은 다양한 옵션을 취합니다.</p>
    <p>참고로 "취소", "열기"를 직접 입력하는 대신, Gtk에서 <em>stock</em> 단추 이름을 활용합니다  스톡 이름은 사용자가 쓰는 언어로 미리 번역해둔 단추 레이블을 활용한다는 점입니다.</p>
    </item>
    <item>
    <p>다음 두 줄은 <gui>열기</gui> 대화 상자에서 GtkImage로만 열 수 있는 파일을 표시하도록 제한합니다. 필터 객체를 우선 만듭니다. 그 다음 <code>GdkPixbuf</code>에서 지원하는 파일 종류(PNG와 JPEG 같은 대부분의 그림 형식)를 필터에 추가합니다. 마지막으로 이 필터를 <gui>열기</gui> 대화 상자의 필터로 설정합니다.</p>
    </item>
    <item>
    <p><code>gtk_dialog_run</code>는 <gui>Open</gui> 대화상자를 보여줍니다. 대화상자는 사용자의 그림 선택을 기다립니다. 사용자가 그림을 선택하면 <code>gtk_dialog_run</code> 함수에서 <code>GTK_RESPONSE_ACCEPT</code> 값을 반환합니다(사용자가 <gui>취소</gui>를 누르면 <code>GTK_RESPONSE_CANCEL</code> 값을 반환합니다). <code>switch</code> 구문은 이 값을 확인합니다.</p>
    </item>
    <item><p>사용자가 <gui>열기</gui>를 눌렀다고 한 상황에서, 다음 줄에서 GtkImage의 <code>file</code> 속성 값을 사용자가 선택한 그림 파일 이름으로 설정합니다. GtkImage는 선택한 그림을 불러오고 화면에 표시합니다.</p>
    </item>
    <item>
    <p>이 메서드의 마지막 줄에서는 <gui>열기</gui> 대화상자는 더 이상 필요 없으니 해체합니다. 해체할 때 대화 상자를 자동으로 숩깁니다.</p>
    </item>
  </list>
</section>

<section id="run">
  <title>프로그램 빌드 및 실행</title>
  <p>모든 코드를 실행할 준비가 됐습니다. <guiseq><gui>빌드</gui><gui>프로젝트 빌드</gui></guiseq>를 눌러 프로젝트 전체를 다시 빌드하고, <guiseq><gui>실행</gui><gui>실행</gui></guiseq>을 눌러 프로그램을 시작하십시오.</p>
  <p>아직 끝나지 않았다면, 화면에 나타나는 대화상자에서 <file>Debug/src/image-viewer</file> 프로그램을 선택하십시오. 마지막으로 <gui>실행</gui>을 누르고 즐기세요!</p>
</section>

<section id="impl">
 <title>참조 구현체</title>
 <p>지침서를 따라하는 실행하는 과정에 문제가 있다면, <link href="image-viewer/image-viewer.c">참조 코드</link>와 여러분의 코드를 비교해보십시오.</p>
</section>

<section id="next">
  <title>다음 단계</title>
  <p>여기 간단한 시험 프로그램에 여러분이 추가로 넣을 수 있는 몇가지 아이디어가 있습니다:</p>
  <list>
   <item>
   <p>파일을 선택하기 보단 디렉터리를 선택하게 하고, 디렉터리의 모든 그림을 보여줄 수 있는 컨트롤을 제어 기능을 제공합니다.</p>
   </item>
   <item>
   <p>사용자가 그림을 불러오고 수정한 그림을 저장할 때 임의 필터와 효과를 그림에 적용하십시오.</p>
   <p><link href="http://www.gegl.org/api.html">GEGL</link>에서는 강력한 그림 편집 기능을 제공합니다.</p>
   </item>
   <item>
   <p>네트워크 공유, 스캐너, 다른 복잡한 공급원에서 그림을 불러올 수 있습니다.</p>
   <p>네트워크 파일 전송 같은 동작을 처리할 때 <link href="http://library.gnome.org/devel/gio/unstable/">GIO</link>를 사용할 수 있습니다. 그리고 스캐너를 다룰 때는 <link href="http://library.gnome.org/devel/gnome-scan/unstable/">그놈 스캔</link>을 활용하시면 됩니다.</p>
   </item>
  </list>
</section>


</page>
