ruby_on_skis 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,98 @@
1
+ # MesagePanelBase will be defined by the XRC generated from
2
+ # wxFormBuilder. Use the "Subclass" property in wxFB for the
3
+ # panel to define it.
4
+ class MessagePanel < MessagePanelBase
5
+ include AppHelper
6
+ include Wx
7
+
8
+ NAME_COL = 0
9
+ DELETE_COL = 1
10
+
11
+ attr_reader :top_window, :editor, :messages, :message_names, :delete
12
+
13
+ def initialize(parent)
14
+ super(parent)
15
+
16
+ @top_window = get_app.get_top_window
17
+
18
+ # wxFormBuilder does not support all widgets. Here is an example of how to
19
+ # include an unsupported widget. Just define a small wxStaticLine in wxFB, then
20
+ # use that as the 'handle' to add the widget to the staticline's container.
21
+
22
+ @editor = StyledTextCtrl.new(self, :style => SUNKEN_BORDER, :border => 10)
23
+ editor.set_wrap_mode 1
24
+ editor.set_margin_width 1, 30
25
+ editor.set_margin_type 1,1 # Line numbers
26
+ editor.set_zoom(5) if Environment.mswin?
27
+ staticline.get_containing_sizer.add(editor,1,EXPAND)
28
+
29
+ evt_button add_button, :on_add_button
30
+ evt_button delete_button, :on_delete_button
31
+ evt_grid_cell_left_click :on_grid_cell_left_click
32
+ evt_grid_cell_left_dclick { | evt | evt.veto }
33
+
34
+ init_grid
35
+ end
36
+
37
+ def delete_col?(column)
38
+ column == DELETE_COL
39
+ end
40
+
41
+ def on_grid_cell_left_click(evt)
42
+ return unless delete_col?(evt.get_col)
43
+ if record_grid.get_cell_value(evt.get_row, DELETE_COL) == "1"
44
+ record_grid.set_cell_value(evt.get_row, DELETE_COL, "0")
45
+ delete.delete(evt.get_row)
46
+ else
47
+ record_grid.set_cell_value(evt.get_row, DELETE_COL, "1")
48
+ delete << evt.get_row
49
+ end
50
+ end
51
+
52
+ def on_add_button
53
+ Message.create!(:name => name_text_ctrl.get_value, :content => editor.get_text)
54
+ record_grid.append_rows(1)
55
+ load_grid
56
+ rescue ActiveRecord::ActiveRecordError => e
57
+ error_alert(e.to_s)
58
+ end
59
+
60
+ def on_delete_button
61
+ delete.each do | index |
62
+ messages[index].destroy
63
+ record_grid.delete_rows(0,1)
64
+ end
65
+ load_grid
66
+ rescue ActiveRecord::ActiveRecordError => e
67
+ error_alert(e.to_s)
68
+ end
69
+
70
+ def init_grid
71
+ @delete = []
72
+
73
+ record_grid.create_grid(Message.count, 2 )
74
+ record_grid.set_col_label_value(NAME_COL, "Name")
75
+ record_grid.set_col_label_value(DELETE_COL, "Delete?")
76
+ record_grid.set_col_format_bool(DELETE_COL)
77
+ record_grid.set_default_cell_alignment(-1, ALIGN_CENTRE)
78
+
79
+ load_grid
80
+ end
81
+
82
+ def load_grid
83
+ @messages = Message.ordered_by_name
84
+ @message_names = Message.names
85
+ delete.clear
86
+ record_grid.clear_grid
87
+
88
+ message_names.each_with_index do | name, i |
89
+ record_grid.set_cell_value(i, NAME_COL, name.truncate(40))
90
+ record_grid.set_read_only(i, NAME_COL)
91
+
92
+ record_grid.set_cell_alignment(i, DELETE_COL, ALIGN_CENTRE, ALIGN_TOP)
93
+ end
94
+
95
+ record_grid.auto_size
96
+ record_grid.get_containing_sizer.layout
97
+ end
98
+ end
@@ -0,0 +1,26 @@
1
+ class MyTaskBarIcon < Wx::TaskBarIcon
2
+ include AppHelper
3
+ TBMENU_RESTORE = 6000
4
+ TBMENU_CLOSE = 6001
5
+ TBMENU_CHANGE = 6002
6
+ TBMENU_REMOVE = 6003
7
+
8
+ def initialize(frame)
9
+ super()
10
+
11
+ @frame = frame
12
+
13
+ # starting image
14
+ icon = make_icon("#{Environment.app_name.underscore}.ico")
15
+ set_icon(icon, "#{Environment.app_name}")
16
+ @image_index = 1
17
+
18
+ # events
19
+ evt_taskbar_left_dclick {|evt| on_taskbar_activate(evt) }
20
+
21
+ evt_menu(TBMENU_RESTORE) {|evt| on_taskbar_activate(evt) }
22
+ evt_menu(TBMENU_CLOSE) { @frame.close }
23
+ evt_menu(TBMENU_CHANGE) {|evt| on_taskbar_change(evt) }
24
+ evt_menu(TBMENU_REMOVE) { remove_icon }
25
+ end
26
+ end
data/lib/wx/app.xrc ADDED
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
@@ -0,0 +1,46 @@
1
+
2
+ # This class was automatically generated from XRC source. It is not
3
+ # recommended that this file is edited directly; instead, inherit from
4
+ # this class and extend its behaviour there.
5
+ #
6
+ # Source file: /Volumes/Projects/ruby_on_skis/lib/wx/app.xrc
7
+ # Generated at: Sun Apr 19 10:53:44 -0500 2009
8
+
9
+ class AppFrameBase < Wx::Frame
10
+
11
+ attr_reader :notebook, :menubar, :file_menu, :quit_menu_item,
12
+ :help_menu, :open, :status_bar
13
+
14
+ def initialize(parent = nil)
15
+ super()
16
+ xml = Wx::XmlResource.get
17
+ xml.flags = 2 # Wx::XRC_NO_SUBCLASSING
18
+ xml.init_all_handlers
19
+ xml.load(File.dirname(__FILE__) + '/../app.xrc')
20
+ xml.load_frame_subclass(self, parent, "AppFrame")
21
+
22
+ finder = lambda do | x |
23
+ int_id = Wx::xrcid(x)
24
+ begin
25
+ Wx::Window.find_window_by_id(int_id, self) || int_id
26
+ # Temporary hack to work around regression in 1.9.2; remove
27
+ # begin/rescue clause in later versions
28
+ rescue RuntimeError
29
+ int_id
30
+ end
31
+ end
32
+
33
+ @notebook = finder.call("notebook")
34
+ @menubar = finder.call("menubar")
35
+ @file_menu = finder.call("file_menu")
36
+ @quit_menu_item = finder.call("quit_menu_item")
37
+ @help_menu = finder.call("help_menu")
38
+ @open = finder.call("Open")
39
+ @status_bar = finder.call("status_bar")
40
+ if self.class.method_defined? "on_init"
41
+ self.on_init()
42
+ end
43
+ end
44
+ end
45
+
46
+
@@ -0,0 +1,45 @@
1
+
2
+ # This class was automatically generated from XRC source. It is not
3
+ # recommended that this file is edited directly; instead, inherit from
4
+ # this class and extend its behaviour there.
5
+ #
6
+ # Source file: /Volumes/Projects/ruby_on_skis/lib/wx/app.xrc
7
+ # Generated at: Sun Apr 19 10:53:44 -0500 2009
8
+
9
+ class MessagePanelBase < Wx::Panel
10
+
11
+ attr_reader :name_label, :name_text_ctrl, :add_button, :staticline,
12
+ :record_grid, :delete_button
13
+
14
+ def initialize(parent = nil)
15
+ super()
16
+ xml = Wx::XmlResource.get
17
+ xml.flags = 2 # Wx::XRC_NO_SUBCLASSING
18
+ xml.init_all_handlers
19
+ xml.load(File.dirname(__FILE__) + '/../app.xrc')
20
+ xml.load_panel_subclass(self, parent, "MessagePanel")
21
+
22
+ finder = lambda do | x |
23
+ int_id = Wx::xrcid(x)
24
+ begin
25
+ Wx::Window.find_window_by_id(int_id, self) || int_id
26
+ # Temporary hack to work around regression in 1.9.2; remove
27
+ # begin/rescue clause in later versions
28
+ rescue RuntimeError
29
+ int_id
30
+ end
31
+ end
32
+
33
+ @name_label = finder.call("name_label")
34
+ @name_text_ctrl = finder.call("name_text_ctrl")
35
+ @add_button = finder.call("add_button")
36
+ @staticline = finder.call("staticline")
37
+ @record_grid = finder.call("record_grid")
38
+ @delete_button = finder.call("delete_button")
39
+ if self.class.method_defined? "on_init"
40
+ self.on_init()
41
+ end
42
+ end
43
+ end
44
+
45
+
@@ -0,0 +1,86 @@
1
+ module AppHelper
2
+ include Wx
3
+
4
+ def error_alert(message)
5
+ alert(message, "Error")
6
+ end
7
+
8
+ def success_alert(message)
9
+ alert(message, "Success")
10
+ end
11
+
12
+ def alert(message, title)
13
+ @top_window ||= get_app.get_top_window
14
+ alert = MessageDialog.new(@top_window, message, title, OK )
15
+ alert.show_modal
16
+ end
17
+
18
+ def confirm(message)
19
+ confirm = Wx::MessageDialog.new(parent, message, "Confirm")
20
+ confirm.show_modal == ID_OK
21
+ end
22
+
23
+ def new_id
24
+ @int ||= 1000
25
+ @int +=1
26
+ end
27
+
28
+ def make_icon(imgname)
29
+ # Different platforms have different requirements for the
30
+ # taskbar icon size
31
+ filename = "#{Environment.app_root}/images/#{imgname}"
32
+ img = Wx::Image.new(filename)
33
+ if Wx::PLATFORM == "WXMSW"
34
+ img = img.scale(16, 16)
35
+ elsif Wx::PLATFORM == "WXGTK"
36
+ img = img.scale(22, 22)
37
+ elsif Wx::PLATFORM == "WXMAC"
38
+ # img = img.scale(16, 16)
39
+ end
40
+ # WXMAC can be any size up to 128x128, so don't scale
41
+ icon = Wx::Icon.new
42
+ icon.copy_from_bitmap(Wx::Bitmap.new(img))
43
+ return icon
44
+ end
45
+
46
+ def status_bar_reset(message="")
47
+ status_bar_update(message)
48
+ get_status_bar.set_background_colour NULL_COLOUR
49
+ end
50
+
51
+ def status_bar_success(message)
52
+ status_bar_update(message)
53
+ get_status_bar.set_background_colour GREEN
54
+ end
55
+
56
+ def status_bar_warning(message)
57
+ status_bar_update(message)
58
+ get_status_bar.set_background_colour YELLOW
59
+ end
60
+
61
+ def status_bar_error(message)
62
+ status_bar_update(message)
63
+ get_status_bar.set_background_colour RED
64
+ end
65
+
66
+ def status_bar_update(message)
67
+ get_status_bar.status_text = message
68
+ end
69
+
70
+ def get_status_bar
71
+ @status_bar ||= get_app.get_top_window.status_bar
72
+ end
73
+
74
+ def open_command(target)
75
+ open_command = if Environment.darwin?
76
+ "open"
77
+ elsif Environment.mswin?
78
+ "start"
79
+ else
80
+ raise "No open command defined for #{RUBY_PLATFORM}"
81
+ end
82
+ Thread.new do
83
+ system("#{open_command} #{target}")
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,14 @@
1
+ class Init < ActiveRecord::Migration
2
+ def self.up
3
+ create_table( :messages ) do |t|
4
+ t.string :name
5
+ t.string :content
6
+ end
7
+ end
8
+
9
+
10
+ def self.down
11
+ drop_table :messages
12
+ end
13
+ end
14
+
@@ -0,0 +1,29 @@
1
+ # The directories you want to include for all platforms are placed in the [:common][:include_dirs] section.
2
+ # The files that you want to include for all platforms are placen in the [:common][:include_files] section.
3
+ # The same idea works for the platform-specific sections. The introspection process to find the files/libraries
4
+ # necessary only works for executable code, so you will have to use these sections to include files that
5
+ # the introspection process does not bring in.
6
+ ---
7
+ :common:
8
+ # Be aware that you will need to reference these directories in the installer.nsi file as well.
9
+ :include_dirs:
10
+ - images
11
+ - config
12
+ - migrate
13
+ :include_files:
14
+ - /lib/wx/app.xrc
15
+ i686-darwin9:
16
+ :include_files:
17
+ - :source: /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/locale/en.yml
18
+ :target: /lib/active_record/locale
19
+ - :source: /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/active_support/locale/en.yml
20
+ :target: /lib/active_support/locale
21
+ i386-mswin32:
22
+ # This key doesn't actually get pulled into the package, it is merely to point to the NSIS executable,
23
+ # to configure that for the package:mswin Rake task.
24
+ :makensis: C:/Program Files/NSIS/makensis.exe
25
+ :include_files:
26
+ - :source: C:/ruby-1.8.7-p72/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/locale/en.yml
27
+ :target: /lib/active_record/locale
28
+ - :source: C:/ruby-1.8.7-p72/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/active_support/locale/en.yml
29
+ :target: /lib/active_support/locale
@@ -0,0 +1,185 @@
1
+ !addincludedir $SMPROGRAMS\NSIS\Include
2
+
3
+ ; Use the Modern UI
4
+ !include "MUI.nsh"
5
+
6
+ ; The name of the installer
7
+ Name "${APP_NAME}"
8
+
9
+ ; The file to write
10
+ OutFile "${APP_NAME_DOWNCASE}-install-${VERSION}.exe"
11
+
12
+ ; The default installation directory
13
+ InstallDir $PROGRAMFILES\${APP_NAME}
14
+
15
+ ; Registry key to check for directory (so if you install again, it will
16
+ ; overwrite the old one automatically)
17
+ InstallDirRegKey HKLM "Software\NSIS_${APP_NAME}" "Install_Dir"
18
+ SetCompressor zlib
19
+
20
+ VIProductVersion ${VERSIONEXTRA}
21
+
22
+ VIAddVersionKey FileVersion ${VERSION}
23
+ VIAddVersionKey FileDescription "${APP_NAME} installer"
24
+ VIAddVersionKey LegalCopyright "Private - No Copying"
25
+ VIAddVersionKey ProductName ${APP_NAME}
26
+
27
+ BrandingText "${APP_NAME} ${VERSION} Installer"
28
+
29
+ ;Interface Settings
30
+
31
+ !define MUI_ABORTWARNING
32
+ !define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\orange-install.ico"
33
+ !define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\orange-uninstall.ico"
34
+ !define MUI_HEADERIMAGE 1
35
+ !define MUI_HEADERIMAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Header\orange.bmp"
36
+ !define MUI_HEADERIMAGE_UNBITMAP "${NSISDIR}\Contrib\Graphics\Header\orange-uninstall.bmp"
37
+ ; Pages
38
+
39
+ !insertmacro MUI_PAGE_COMPONENTS
40
+ !insertmacro MUI_PAGE_DIRECTORY
41
+ !insertmacro MUI_PAGE_INSTFILES
42
+
43
+ !insertmacro MUI_UNPAGE_CONFIRM
44
+ !insertmacro MUI_UNPAGE_INSTFILES
45
+
46
+ !insertmacro MUI_LANGUAGE "English"
47
+ ;--------------------------------
48
+
49
+ ; The stuff to install
50
+ Section "${APP_NAME}" SecCore
51
+ SectionIn RO
52
+
53
+ ; Set output path to the installation directory.
54
+ SetOutPath $INSTDIR
55
+
56
+ ; Put all the build files there
57
+ ; File /r build\*.*
58
+ File /r ${BUILD_DIR}\*.*
59
+ ; And the standard ruby script
60
+ ;File /r mswin-init.rb
61
+
62
+ ; Write the installation path into the registry
63
+ WriteRegStr HKLM SOFTWARE\NSIS_${APP_NAME} "Install_Dir" "$INSTDIR"
64
+
65
+ ; back up old value of ${APP_DOC_EXTENSION}
66
+ !define Index "Line${__LINE__}"
67
+ ReadRegStr $1 HKCR "${APP_DOC_EXTENSION}" ""
68
+ StrCmp $1 "" "${Index}-NoBackup"
69
+ StrCmp $1 "${APP_NAME}" "${Index}-NoBackup"
70
+ WriteRegStr HKCR "${APP_DOC_EXTENSION}" "backup_val" $1
71
+ "${Index}-NoBackup:"
72
+
73
+ WriteRegStr HKCR "${APP_DOC_EXTENSION}" "" "${APP_NAME}"
74
+ ReadRegStr $0 HKCR "${APP_NAME}" ""
75
+ StrCmp $0 "" 0 "${Index}-Skip"
76
+
77
+ WriteRegStr HKCR "${APP_NAME}" "" "${APP_NAME}"
78
+ "${Index}-Skip:"
79
+ WriteRegStr HKCR "${APP_NAME}\shell" "" "open"
80
+ WriteRegStr HKCR "${APP_NAME}\DefaultIcon" "" "$INSTDIR\share\icons\project.ico"
81
+ WriteRegStr HKCR "${APP_NAME}\shell\open\command" "" '$INSTDIR\${APP_NAME_DOWNCASE}.exe "%1"'
82
+ !undef Index
83
+
84
+ ; Write the uninstall keys for Windows
85
+ WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" "DisplayName" "NSIS ${APP_NAME}"
86
+ WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" "UninstallString" '"$INSTDIR\uninstall.exe"'
87
+ WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" "NoModify" 1
88
+ WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" "NoRepair" 1
89
+ WriteUninstaller "uninstall.exe"
90
+
91
+ SectionEnd
92
+
93
+ LangString DESC_SecCore ${LANG_ENGLISH} "${APP_NAME} software (required)"
94
+
95
+ ; Optional section (can be disabled by the user)
96
+ Section "Start Menu Shortcuts" SecShortcuts
97
+
98
+ SetOutPath "$INSTDIR\bin"
99
+ CreateDirectory "$SMPROGRAMS\${APP_NAME}"
100
+ CreateShortCut "$SMPROGRAMS\${APP_NAME}\${APP_NAME}.lnk" "$INSTDIR\bin\${APP_NAME_DOWNCASE}.exe" "pinit.rb" "$INSTDIR\images\${APP_NAME_DOWNCASE}.ico" 0
101
+ CreateShortCut "$INSTDIR\${APP_NAME}.lnk" "$SYSDIR\wscript.exe" "run.vbs" "$INSTDIR\images\${APP_NAME_DOWNCASE}.ico" 0
102
+ SetOutPath $INSTDIR
103
+ CreateShortCut "$SMPROGRAMS\${APP_NAME}\${APP_NAME} Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\images\${APP_NAME_DOWNCASE}.ico" 0
104
+
105
+ SectionEnd
106
+
107
+ LangString DESC_SecShortcuts ${LANG_ENGLISH} "Add shortcuts to ${APP_NAME} to the Windows start menu (recommended)"
108
+
109
+ ; Optional section (can be disabled by the user)
110
+ Section "Quicklaunch Shortcut" SecQShortcut
111
+
112
+ SetOutPath "$INSTDIR\bin"
113
+ ; CreateDirectory "$SMPROGRAMS\${APP_NAME}"
114
+ CreateShortCut "$QUICKLAUNCH\${APP_NAME}.lnk" "$INSTDIR\bin\${APP_NAME_DOWNCASE}.exe" "pinit.rb" "$INSTDIR\images\${APP_NAME_DOWNCASE}.ico" 0
115
+
116
+ SectionEnd
117
+
118
+ LangString DESC_SecQShortcut ${LANG_ENGLISH} "Add Quicklaunch shortcut to ${APP_NAME} (recommended)"
119
+
120
+ ;Section "Help and Documentation" SecHelpfiles
121
+
122
+ ; Set output path to the installation directory.
123
+ ; SetOutPath $INSTDIR
124
+ ;File "doc\wefthelp.chm"
125
+ ;File "doc\wefthelp.pdf"
126
+ ;SectionEnd
127
+ ; LangString DESC_SecHelpfiles ${LANG_ENGLISH} "Install the ${APP_NAME} help file and documentation (recommended)"
128
+
129
+ !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
130
+ !insertmacro MUI_DESCRIPTION_TEXT ${SecCore} $(DESC_SecCore)
131
+ !insertmacro MUI_DESCRIPTION_TEXT ${SecShortcuts} $(DESC_SecShortcuts)
132
+ !insertmacro MUI_DESCRIPTION_TEXT ${SecQShortcut} $(DESC_SecQShortcut)
133
+ ;!insertmacro MUI_DESCRIPTION_TEXT ${SecHelpfiles} $(DESC_SecHelpfiles)
134
+ !insertmacro MUI_FUNCTION_DESCRIPTION_END
135
+
136
+ ; Uninstaller
137
+
138
+ Section "Uninstall"
139
+
140
+ ; Remove registry keys
141
+ DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}"
142
+ DeleteRegKey HKLM SOFTWARE\NSIS_${APP_NAME}
143
+
144
+ ; Delete the installed files
145
+ ; RMDir /r "$INSTDIR\share"
146
+ RMDir /r "$INSTDIR\lib"
147
+ RMDir /r "$INSTDIR\bin"
148
+ RMDir /r "$INSTDIR\config"
149
+ RMDir /r "$INSTDIR\images"
150
+ RMDir /r "$INSTDIR\migrate"
151
+ ; RMDir /r "$INSTDIR\doc"
152
+ ; Delete "$INSTDIR\*.dll"
153
+ Delete "$INSTDIR\*.lnk"
154
+ ; Delete "$INSTDIR\${APP_NAME_DOWNCASE}*"
155
+ Delete "$INSTDIR\uninstall.exe"
156
+ RMDir $INSTDIR
157
+
158
+ ; Remove shortcuts, if any
159
+ Delete "$SMPROGRAMS\${APP_NAME}\*.*"
160
+ Delete "$SMPROGRAMS\${APP_NAME}\*.*"
161
+ Delete "$QUICKLAUNCH\${APP_NAME}.lnk"
162
+
163
+ ; Remove directories used
164
+ RMDir "$SMPROGRAMS\${APP_NAME}"
165
+ RMDir "$SMPROGRAMS\${APP_NAME}"
166
+
167
+
168
+ ;start of restore script
169
+ !define Index "Line${__LINE__}"
170
+ ReadRegStr $1 HKCR "${APP_DOC_EXTENSION}" ""
171
+ StrCmp $1 "${APP_NAME}" 0 "${Index}-NoOwn" ; only do this if we own it
172
+ ReadRegStr $1 HKCR "${APP_DOC_EXTENSION}" "backup_val"
173
+ StrCmp $1 "" 0 "${Index}-Restore" ; if backup="" then delete the whole key
174
+ DeleteRegKey HKCR "${APP_DOC_EXTENSION}"
175
+ Goto "${Index}-NoOwn"
176
+ "${Index}-Restore:"
177
+ WriteRegStr HKCR "${APP_DOC_EXTENSION}" "" $1
178
+ DeleteRegValue HKCR "${APP_DOC_EXTENSION}" "backup_val"
179
+
180
+ DeleteRegKey HKCR "${APP_NAME}" ;Delete key with association settings
181
+
182
+ "${Index}-NoOwn:"
183
+ !undef Index
184
+
185
+ SectionEnd