'Ribbon'에 해당하는 글 2건


이 글의 원본은 훈스닷넷에 있고 지난 강좌는 여기에 있습니다.

두번째 강좌의 소스코드 다운로드


Ribbon 탭과 그룹 적용
Ribbon 인터페이스는 탭 컨트롤이 적용되어 있습니다. 명령과 기능들을 잘 정의하고 정리해서 탭을 만들고 탭에서 그룹으로 잘 묶어줘야 좋은 UI가 나오겠죠.
“홈”과 “공유” 두 가지 RibbonTab을 만들겠습니다.

저는 메인 기능을 홈 탭으로 묶으려 하고 공유와 관련된 기능을 공유라는 탭으로 묶으려고 하고 있습니다. 아무래도 홈 탭에는 “도구, 모양, 색” 이렇게 3가지 그룹을 넣고 공유 탭에는 “SNS”라는 탭을 만들어서 묶어보겠습니다. 이런 구조가 나오겠네요.

도구

지우개, 연필 (서로 토글)

모양

연필의 브러시 모양 지정

연필에 적용될 색

공유

SNS

트위터, 페이스북

Command들이 많아지네요. 버튼마다 기능이 있고 그 기능들은 명령으로 구현할 수 있습니다.

우선 그룹에 쓰일 명령을 만들어봤습니다

<r:RibbonCommand x:Key="ToolsGroupCommand" LabelTitle="도구" LargeImageSource="Images\Transfer.png" SmallImageSource="Images\Transfer.png" />

        <r:RibbonCommand x:Key="BrushGroupCommand" LabelTitle="모양" LargeImageSource="Images\brush.png" SmallImageSource="Images\brush.png" />

        <r:RibbonCommand x:Key="ColorGroupCommand" LabelTitle="" LargeImageSource="Images\color.png" SmallImageSource="Images\color.png" />

        <r:RibbonCommand x:Key="SNSGroupCommand" LabelTitle="SNS" LargeImageSource="Images\twitter.png" SmallImageSource="Images\twitter.png" />


이 Command를  <r:RibbonGroup Command="{StaticResource ToolsGroupCommand}"> 형식으로 RibbonGroup에 붙여 줍니다.

각 그룹에는 해당하는 버튼들을 위치 시킬 수 있는데요. 그 버튼들 마다 하나의 Command를 만들어서 적용해 보겠습니다. Command가 많다 보니까 만드는게 힘드네요.
(Visual Studio 2010의 XAML을 그대로 Word에 붙여넣기 하면 왜 아래처럼 한글이 깨지는지 모르겠어요.)

<r:RibbonCommand x:Key="EraserCommand"

                         LabelTitle="지우개"

                         LabelDescription="o¯iÆ©ø¬| ù¡¾AI¯¨Ï ù¡¾¡í o¯iùo OöA¥I¥U."

                         SmallImageSource="Images\eraser.png"

                         LargeImageSource="Images\eraser.png"

                         ToolTipTitle="o¯iÆ©ø"

                         ToolTipDescription="o¯iÆ©ø¬| ù¡¾AI¯¨Ï ù¡¾¡í o¯iùo OöA¥I¥U."

                         CanExecute="EraserCommand_CanExecute"

                         Executed="EraserCommand_Executed"/>

 

        <r:RibbonCommand x:Key="BrushCommand"

                         LabelTitle="ù¡¾¾¡¿¬¢ç¾a"

                         LabelDescription="ù¡¾¾¡¿¬¢ç¾a¬| ù¡¾AI¯¨Ï ù¡¾¡í ¾¡¿¬¡¾ùo OöA¥I¥U."

                         SmallImageSource="Images\brush.png"

                         LargeImageSource="Images\brush.png"

                         ToolTipTitle="ù¡¾¾¡¿¬¢ç¾a"

                         ToolTipDescription="ù¡¾¾¡¿¬¢ç¾a¬| ù¡¾AI¯¨Ï ù¡¾¡í ¾¡¿¬¡¾ùo OöA¥I¥U."

                         CanExecute="BrushCommand_CanExecute"

                         Executed="BrushCommand_Executed"/>

 

<!-- 나머지는 소스 코드 참조-->


이 Command를 아래 코드처럼 RibbonButton에 적용할수 있습니다.

<r:RibbonTab Label="">

<r:RibbonGroup Command="{StaticResource ToolsGroupCommand}">

<r:RibbonButton Command="{StaticResource BrushCommand}" />

<r:RibbonButton Command="{StaticResource EraserCommand}" />

</r:RibbonGroup>

<r:RibbonGroup Command="{StaticResource BrushGroupCommand}">

<r:RibbonButton Command="{StaticResource CircleShapeCommand}" />

<r:RibbonButton Command="{StaticResource StarShapeCommand}" />

</r:RibbonGroup>

<r:RibbonGroup Command="{StaticResource ColorGroupCommand}">

<r:RibbonButton Command="{StaticResource RedColorCommand}" />

<r:RibbonButton Command="{StaticResource BlueColorCommand}" />

<r:RibbonButton Command="{StaticResource GreenColorCommand}" />

</r:RibbonGroup>

</r:RibbonTab>

 

<r:RibbonTab Label="공유">

<r:RibbonGroup  Command="{StaticResource SNSGroupCommand}">

<r:RibbonButton Command="{StaticResource TwitterCommand}" />

<r:RibbonButton Command="{StaticResource FacebookCommand}" />

</r:RibbonGroup>

</r:RibbonTab>


실행결과는 이렇습니다.
(아이콘들은 구글 이미지 검색에서 가져왔습니다.)

버튼들이 원하는 대로 그룹으로 묶여 있습니다. 탭도 정상적으로 작동을 하고 있죠.

Ribbon은 RibbonButton말고 다양한 컨트롤을 제공하고 있습니다.

• RibbonButton
• RibbonCheckBox
• RibbonToggleButton
• RibbonDropDownButton
• RibbonSplitButton
• RibbonComboBox
• RibbonTextBox
• RibbonLabel
• RibbonSeparator

RibbonDropDownButton을 써볼까요? 색 그룹을 아래 코드처럼 변경해보세요.,

<r:RibbonGroup Command="{StaticResource ColorGroupCommand}">

<r:RibbonDropDownButton Command="{StaticResource RedColorCommand}">

<MenuItem Header="Red" />

<MenuItem Header="Green" />

<MenuItem Header="Blue" />

</r:RibbonDropDownButton>

</r:RibbonGroup>



이런식으로 체크박스, 토글버튼, 텍스트 박스 등을 사용할 수 있을 것 같습니다.

한가지 더 재미있는 것이 남았습니다. 오피스를 실행하고 창 크기를 변경해보면 Ribbon의 그룹과 그 그룹에 속한 컨트롤들이 점차 줄어들어 작아진 윈도우에 최적화 되는걸 볼 수 있습니다.



이것을 구현하는 속성이 RibbonGroup의 GroupSizeDefinitions 속성입니다.
리소스 부분에 RibbonGroupSizeDefinitionCollection 을 아래와 같이 추가합니다. 이 정의는 창이 줄어들 때 어떤 방식으로 정리를 할 것인지에 대한 내용입니다.

<r:RibbonGroupSizeDefinitionCollection x:Key="RibbonLayout">

            <r:RibbonGroupSizeDefinition>

                <!-- Control sizes: L,L,L -->

                <r:RibbonControlSizeDefinition ImageSize="Large" IsLabelVisible="True"/>

                <r:RibbonControlSizeDefinition ImageSize="Large" IsLabelVisible="True"/>

                <r:RibbonControlSizeDefinition ImageSize="Large" IsLabelVisible="True"/>

            </r:RibbonGroupSizeDefinition>

            <r:RibbonGroupSizeDefinition>

                <!-- Control sizes: L,M,M -->

                <r:RibbonControlSizeDefinition ImageSize="Large" IsLabelVisible="True"/>

                <r:RibbonControlSizeDefinition ImageSize="Small" IsLabelVisible="True"/>

                <r:RibbonControlSizeDefinition ImageSize="Small" IsLabelVisible="True"/>

            </r:RibbonGroupSizeDefinition>

            <r:RibbonGroupSizeDefinition>

                <!-- Control sizes: L,S,S -->

                <r:RibbonControlSizeDefinition ImageSize="Large" IsLabelVisible="True"/>

                <r:RibbonControlSizeDefinition ImageSize="Small" IsLabelVisible="False"/>

                <r:RibbonControlSizeDefinition ImageSize="Small" IsLabelVisible="False"/>

            </r:RibbonGroupSizeDefinition>

            <!-- Collapsed -->

            <r:RibbonGroupSizeDefinition IsCollapsed="True" />

        </r:RibbonGroupSizeDefinitionCollection>


이 정의를 적용합니다.

<r:RibbonTab Label="¡§">

                    <r:RibbonGroup Command="{StaticResource ToolsGroupCommand}" GroupSizeDefinitions="{StaticResource RibbonLayout}">

                        <r:RibbonButton Command="{StaticResource BrushCommand}" />

                        <r:RibbonButton Command="{StaticResource EraserCommand}" />

                    </r:RibbonGroup>

                    <r:RibbonGroup Command="{StaticResource BrushGroupCommand}" GroupSizeDefinitions="{StaticResource RibbonLayout}">

                        <r:RibbonButton Command="{StaticResource CircleShapeCommand}" />

                        <r:RibbonButton Command="{StaticResource StarShapeCommand}" />

                    </r:RibbonGroup>

                    <r:RibbonGroup Command="{StaticResource ColorGroupCommand}" GroupSizeDefinitions="{StaticResource RibbonLayout}">

                        <r:RibbonButton Command="{StaticResource RedColorCommand}" />

                        <r:RibbonButton Command="{StaticResource BlueColorCommand}" />

                        <r:RibbonButton Command="{StaticResource GreenColorCommand}" />

</r:RibbonGroup>

                </r:RibbonTab>

 


실행을 한 후에 창의 크기를 줄여나가면 아래 그림과 같이 그룹들이 정렬이 되고 버튼들이 재배치 되는걸 볼 수 있습니다.

 

 

그런데 창이 어느 한계에 가면 리본이 사라지는 현상이 있는데 왜일까요? CTP 버전의 버그 인 줄 알았는데 오피스도 그러네요. ‘창이 너무 작아지면 UI가 의미가 없으니 사라진다라고 생각하면 좋을 것 같습니다.

 

지금까지 Ribbon의 기본 사용법에 대해서 2회에 걸쳐서 강좌를 올렸습니다. WPF에서 XAML과 함께 사용하는 것은 이처럼 어렵지 않습니다. 남은 것은 탭과 그룹을 잘 설계해서 사용자들에게 실질적인 도움을 주는 것이겠죠.

 

감사합니다.

 


WRITTEN BY
ONESTONE

트랙백  0 , 댓글  0개가 달렸습니다.
secret


이 글의 원본은 훈스닷넷에 있습니다.

강좌에 사용한 소스코드 다운로드


(RibbonControlsLibrary.dll 은 아래 글을 읽고 다운로드 받아서 사용하세요. 라이센스가 있어 그렇습니다.)

Ribbon 개요
Ribbon 사용자 인터페이스는 Microsoft Office 2007부터 적용이 되어 사용되고 있습니다. Windows 7에서는 그림판에도 적용이 되었죠. 툴바와 메뉴에 익숙하던 윈도우 사용자들이 처음 Ribbon 인터페이스를 접하고 조금 당황해 하기도 했지만 사용하면 할수록 쉽고 편리하다는 걸 느낄 수 있습니다. 그 편리함이 단지 익숙해져서 그렇기도 하겠지만 UX에 대한 깊은 연구가 바탕이 되었습니다. Office UI 팀이 Ribbon을 만들고 적용하기까지의 과정을 살펴보려면 MIX09의 The Story of the Ribbon (http://videos.visitmix.com/MIX08/UX09) 세션을 한번 보세요. UX에 관심이 많으신 분들 보시면 좋을 것 같습니다.

WPF에서는 Ribbon 인터페이스를 사용할 수 있습니다. 아직은 CTP 버전이지만 Ribbon의 기본기능들은 모두 구현이 되어 있습니다. 이 강좌에서 Ribbon의 기초적인 사용법을 같이 살펴보겠습니다.

사실 Ribbon을 쉽게 보면 Office와 비슷한 UI를 만드는 것이지만 Office 만큼 사용하기 쉽게 만들기 위해서는 많은 고민이 필요합니다. 그런 고민에 도움을 줄 수 있는 많은 글들이 Office 사이트에 있습니다. Ribbon UI를 심각하게 사용하실 분은 꼭 참조를 해야겠지만 이 글에서는 우선 Ribbon을 사용하는 방법에 집중을 해보겠습니다. 

Ribbon 컨트롤 다운로드 (RibbonControlsLibrary.dll)
RibbonControlsLibrary.dll의 다운로드는 Office UI Licensing Site에서 다운로드 받을 수 있습니다. 아래의 절차를 따라서 해보세요.

  1. Office UI Licensing Site 에 접속하고 License the Office UI 링크를 눌러 들어갑니다. 
  2. Live ID로 로그인을 합니다. 
  3. 몇 가지 정보를 입력하고 라이선스 사용에 동의를 한 후 Finish 버튼을 눌러 전송합니다. 
  4. Microsoft Office Fluent UI Design Guidelines File Download 페이지에서 “WPF Ribbon Control: Binary & Link to Sample Application”을 눌러 다운로드 받습니다. 디자인 가이드라인도 제공을 하고 있습니다. 
  5. 압축된 파일을 풀면 RibbonControlsLibrary.dll을 확인 할 수 있습니다.


Ribbon 컨트롤 올리기
우선 리본 컨트롤을 윈도우에 올려봅시다.

1. 먼저 Visual Studio 2010을 열고 적당한 이름으로 WPF 프로젝트를 생성합니다. (물론 Visual Studio 2008에서도 사용 가능합니다.) 저는 Visual Studio 2010에서 RibbonInkCanvas라는 이름으로 프로젝트를 생성 했습니다.

2. 다운로드 받은 RibbonControlsLibrary.dll을 프로젝트에 참조로 추가합니다.

3. MainWidnows.xaml을 열어서 네임스페이스를 추가합니다. 저는 r 이라는 접두사를 사용했습니다.

xmlns:r="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"

4. 윈도우 상단에 리본을 붙여 봅시다. 리본은 상단에 붙어 있어야 하므로 StackPanel 을 사용하는 것이 좋겠네요. 아래 XAML 코드 처럼 StackPanel을 추가하고 방향을 Vertical 로 설정합니다.

5. 드디어 Ribbon 을 추가합니다.

<Window x:Class="RibbonInkCanvas.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:r="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"

        Title="MainWindow" Height="350" Width="525">

    <Grid>

        <StackPanel Orientation="Vertical">

            <r:Ribbon DockPanel.Dock="Top">

              

            </r:Ribbon>

        </StackPanel>

    </Grid>

</Window>


실행한 결과는 아래와 같습니다. 껍데기가 붙어있는 상황이네요.



Ribbon 인터페이스의 구조
리본 인터페이스의 구조를 알아야 적용을 할 수 있습니다. 아래 그림을 보면 그 구조가 보입니다. 그냥 쓸 때는 몰랐는데 만들려고 하니 뭐가 많군요.

<출처 : MSDN>

  • Office 메뉴를 보니까 Application Button은 파일 관련된 메뉴(저장, 새로 만들기 등)를 넣으면 되겠고 프로그램을 종료하는 메뉴가 있으면 되겠네요. 
  • Quick Access Toolbar 도 있었네요. 자주 사용하는 몇 가지가 들어가면 되겠어요. 
  • Tab 이 있네요. 리본은 기본적으로 탭구조를 가지고 있죠. 
  • Tab 중에 상황에 맞게 생기는 Contextual Tab도 있구요. 이게 상당히 유용하던데. 
  • Tab 안에 기능들을 Group으로 묶어주고 그 중에 In-Ribbon Gallery라고 그림으로 한눈에 알아볼 수 있는 명령들이 있죠. 
  • 잘 사용하지 않던 건데 Dialog Box Launcher를 누르니까 리본 이전에 많이 사용하던 대화상자가 뜨네요. 
  • Enhanced Tooltips은 자세한 설명이 들어있는 툴팁을 표시해 줍니다.

이 강좌에서 위의 모든 것을 구현하지는 못하지만 기본은 해보죠.

Application Menu 버튼과 Enhanced Tooltips, 그리고 탭, Quick Launch Toolbar을 만들어서 그 안에 명령들을 유사한 그룹으로 묶어서 메뉴를 만들어 보겠습니다.

그럴싸하게 만들려면 아이콘들이 좀 필요한데 Ribon Sample에서 조금 가져다 쓰도록 하죠. 소스를 다운로드 받아서 Image 폴더의 아이콘을 우리가 작업하는 프로젝트에 넣습니다.


Application Menu 추가
아래 그림은 윈도우7의 그림판의 Application Menu입니다.

메뉴들을 살펴보니 어떤 것들이 들어가면 좋을지 감이오네요. 여기에서는 새로 만들기/저장/닫기 등의 메뉴를 만들어 봅시다.

먼저 RibbonCommand를 이용해서 필요한 커멘드를 만들고 인터페이스에 적용을 하는 식으로 진행을 해봅시다. WPF에서는 초창기부터 Command 패턴을 적용한 구조를 가지고 있습니다. 사용자가 하려는 행동을 Command로 만들고 그것을 XAML을 통해서 인터페이스에 붙이고 실행되어야 하는 코드는 코드 비하인드에서 처리하는 방식인데요. 먼저 Command Pattern을 이해하시고 MSDN의 명령 개요를 읽어보시면 이해를 하실 수 있습니다.

Command를 사용하면 코드의 구현과 UI를 분리할 수 있고 Command를 재사용 할 수 있습니다. 예를 들어 ‘저장’이라는 버튼은 리본 인터페이스에서 Application Menu, Quick Access Toolbar, 어떤 Tab에 삽입된 버튼 등 여러 곳에서 사용 가능합니다. 이럴 때 Command 를 만들어서 여러 UI에 붙이고 실행되는 코드는 한 곳으로 만들 수 있습니다.

리본에서도 RibbonCommand라는 클래스를 제공합니다. 리본 커멘드 3가지를 만들어서 Windows 리소스에 추가를 해봅시다.

RibbonCommand의 주요 속성은 아래와 같습니다.

LabelTitle

 

LabelDescription

 

ToolTipTitle

 

ToolTipDescription

 

SmallImageSource

 

LargeImageSource

 

RibbonCommand의 주요 이벤트는 아래 표와 같습니다.

CanExcute

메뉴는 상황에 따라서 비활성화/활성화 될 필요가 있습니다. 이 이벤트의 핸들러에서 CanExecuteRoutedEventArgsCanExecute 속성을 False로 해주면 해당 메뉴가 비활성화 됩니다.

Excuted

명령이 실행될 때 이벤트 발생. 이벤트 핸들러에서 해당 명령에 해당하는 코드를 실행해 주면 됩니다.

아래 XAML 코드처럼 3가지 RibbonCommand를 만들고 Application Menu를 추가해 봅시다.

<Window x:Class="RibbonInkCanvas.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:r="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"

        Title="MainWindow" Height="350" Width="525">

    <Window.Resources>

        <r:RibbonCommand x:Key="CloseCommand"

                         LabelTitle="닫기"

                         LabelDescription=" 프로그램을 종료합니다."

                         ToolTipTitle="프로그램 닫기"

                         ToolTipDescription=" 프로그램을 종료합니다. 종료하기 전에 변경된 데이터를 저장하시기 바랍니다."

                         SmallImageSource="Images\delete.png"

                         LargeImageSource="Images\delete.png"

                         CanExecute="CloseCommand_CanExecute" 

                         Executed="CloseCommand_Executed"/>

        <r:RibbonCommand x:Key="SaveCommand"

                         LabelTitle="저장"

                         LabelDescription=" 변경된 내용을 저장합니다."

                         ToolTipTitle=" 변경된 내용 저장"

                         ToolTipDescription=" 변경된 내용을 저장합니다."

                         SmallImageSource="Images\save.png"

                         LargeImageSource="Images\save.png" 

                         CanExecute="SaveCommand_CanExecute"

                         Executed="SaveCommand_Executed"/>

        <r:RibbonCommand x:Key="NewCommand"

                         LabelTitle="새로만들기 "

                         LabelDescription="새로운 그리기를 시작합니다."

                         ToolTipTitle="새로만들기"

                         ToolTipDescription="새로운 그리기를 시작합니다."

                         SmallImageSource="Images\files.png"

                         LargeImageSource="Images\files.png"

                         CanExecute="NewCommand_CanExecute"

                         Executed="NewCommand_Executed"/>

        <r:RibbonCommand x:Key="ApplicatioMenuCommand"

                         LabelTitle="Application Button"

                         LabelDescription="Application Button."

                         SmallImageSource="images/Pencil.png"

                         LargeImageSource="images/Pencil.png"

                         ToolTipTitle="Ribbon Ink Canvas"

                         ToolTipDescription="Click here to open Ribbon IncCanvas Menu." />

 

    </Window.Resources>

    <Grid>

        <StackPanel Orientation="Vertical">

            <r:Ribbon DockPanel.Dock="Top">

                <r:Ribbon.ApplicationMenu>

                    <r:RibbonApplicationMenu Command="{StaticResource ApplicatioMenuCommand}" >

                        <r:RibbonApplicationMenuItem Command="{StaticResource NewCommand}" />

                        <r:RibbonApplicationMenuItem Command="{StaticResource SaveCommand}" />

                        <r:RibbonSeparator />

                        <r:RibbonApplicationMenuItem Command="{StaticResource CloseCommand}" />

                    </r:RibbonApplicationMenu>

                </r:Ribbon.ApplicationMenu>

            </r:Ribbon>

        </StackPanel>

    </Grid>

</Window>

 


코드 비하인드(MainWindow.xaml.cs)에도 오류가 나지 않도록 아래와 같이 RibbonCommand의 이벤트 핸들러를 넣어줍니다.

private void CloseCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)

{

e.CanExecute = true;

}

private void SaveCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)

{

   e.CanExecute = true;

}

private void NewCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)

{

   e.CanExecute = true;

 }

private void CloseCommand_Executed(object sender, ExecutedRoutedEventArgs e)

{

}

private void SaveCommand_Executed(object sender, ExecutedRoutedEventArgs e)

{

}

private void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e)

{

}

코드를 실행하면 Application Menu가 생성된 것을 볼 수 있습니다. RibbonSeparator를 사용해서 메뉴에 가로선을 넣을 수도 있네요.



Quick Launch Toolbar 만들기.
아래 XAML 코드를 추가하면 Quick Launch Toolbar에 아이콘을 추가 할 수 있습니다. 

...
<
r:Ribbon.QuickAccessToolBar>

<r:RibbonQuickAccessToolBar>

<r:RibbonButton Command="{StaticResource NewCommand}"                                               

r:RibbonQuickAccessToolBar.Placement="InCustomizeMenu"/>

<r:RibbonButton Command="{StaticResource SaveCommand}"                                                

r:RibbonQuickAccessToolBar.Placement="InCustomizeMenuAndToolBar"/>

</r:RibbonQuickAccessToolBar>

</r:Ribbon.QuickAccessToolBar>

 ...



r:RibbonQuickAccessToolBar.Placement 속성에는 3가지 값(InCustomizeMenuAndToolBar, InCustomizeMenu, InToolBar)이 들어갈 수 있는데 값을 변경하면서 실행을 해보시면 용도를 알 수 있습니다. InCustomizeMenuAndToolBar로 지정하면 버튼도 보이고 버튼을 커스터마이징 할 수 있는 메뉴에도 들어갑니다. 

실행을 해보면 Quick Lanch Toolbar가 추가된 것을 확인할 수 있습니다. 새로 만들기 버튼은 "InCustomizeMenu"에만 추가되어 있는 걸 확인 할 수 있습니다.



Application Menu와 Quick Launch Menu까지 추가를 했습니다.

 (2편에서 계속)


WRITTEN BY
ONESTONE

트랙백  0 , 댓글  0개가 달렸습니다.
secret