/[svn]/jsampler/trunk/src/org/jsampler/view/classic/ClassicPrefs.java
ViewVC logotype

Contents of /jsampler/trunk/src/org/jsampler/view/classic/ClassicPrefs.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1285 - (show annotations) (download)
Fri Aug 10 19:55:03 2007 UTC (16 years, 8 months ago) by iliev
File size: 20843 byte(s)
* Updated to version 0.6a. The Fantasia distribution is now
  capable of controlling all features available in LinuxSampler

1 /*
2 * JSampler - a java front-end for LinuxSampler
3 *
4 * Copyright (C) 2005-2007 Grigor Iliev <grigor@grigoriliev.com>
5 *
6 * This file is part of JSampler.
7 *
8 * JSampler is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation.
11 *
12 * JSampler is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with JSampler; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * MA 02111-1307 USA
21 */
22
23 package org.jsampler.view.classic;
24
25 import java.awt.Color;
26
27 import java.util.prefs.Preferences;
28
29 import org.jsampler.CC;
30
31 import org.jsampler.view.std.StdPrefs;
32
33
34 /**
35 * This class represents the preferences of the JS Classic package.
36 * @author Grigor Iliev
37 */
38 public class ClassicPrefs extends StdPrefs {
39 private final static String prefNode = "org.jsampler.view.classic";
40
41 private final static String WINDOW_SIZE_AND_LOCATION = ".sizeAndLocation";
42 private final static String DEF_WINDOW_SIZE_AND_LOCATION = null;
43
44 private final static String WINDOW_MAXIMIZED = ".maximized";
45 private final static boolean DEF_WINDOW_MAXIMIZED = false;
46
47 private final static String SAVE_WINDOW_PROPERTIES = "Mainframe.saveProperties";
48 private final static boolean DEF_SAVE_WINDOW_PROPERTIES = true;
49
50 private final static String HSPLIT_DIVIDER_LOCATION = "HSplit.dividerLocation";
51 private final static int DEF_HSPLIT_DIVIDER_LOCATION = 180;
52
53 private final static String SAVE_LEFT_PANE_STATE = "LeftPane.saveState";
54 private final static boolean DEF_SAVE_LEFT_PANE_STATE = true;
55
56 private final static String LEFT_PANE_PAGE_IDX = "LeftPane.pageIndex";
57 private final static int DEF_LEFT_PANE_PAGE_IDX = 0;
58
59 private final static String SHOW_CHANNELS_BAR = "ChannelsBar.visible";
60 private final static boolean DEF_SHOW_CHANNELS_BAR = true;
61
62 private final static String SHOW_STATUSBAR = "Statusbar.visible";
63 private final static boolean DEF_SHOW_STATUSBAR = true;
64
65 private final static String SHOW_LEFT_PANE = "LeftPane.visible";
66 private final static boolean DEF_SHOW_LEFT_PANE = true;
67
68 private final static String SHOW_STANDARD_BAR = "StandardBar.visible";
69 private final static boolean DEF_SHOW_STANDARD_BAR = true;
70
71 private final static String SHOW_LS_CONSOLE = "LSConsole.visible";
72 private final static boolean DEF_SHOW_LS_CONSOLE = false;
73
74 private final static String LS_CONSOLE_POPOUT = "LSConsole.popout";
75 private final static boolean DEF_LS_CONSOLE_POPOUT = false;
76
77 private final static String CHANNEL_BORDER_COLOR = "Channel.borderColor";
78 private final static int DEF_CHANNEL_BORDER_COLOR = 0xb8cfe5;
79
80 private final static String CUSTOM_CHANNEL_BORDER_COLOR = "Channel.customBorderColor";
81 private final static boolean DEF_CUSTOM_CHANNEL_BORDER_COLOR = false;
82
83 private final static String CHANNEL_BORDER_HL_COLOR = "Channel.borderMouseOverColor";
84 private final static int DEF_CHANNEL_BORDER_HL_COLOR = 0xb8cfe5;
85
86 private final static String CUSTOM_CHANNEL_BORDER_HL_COLOR = "Channel.customHlColor";
87 private final static boolean DEF_CUSTOM_CHANNEL_BORDER_HL_COLOR = false;
88
89 private final static String SEL_CHANNEL_BG_COLOR = "Channel.sel.BgColor";
90 private final static int DEF_SEL_CHANNEL_BG_COLOR = 0xe0e6eb;
91
92 private final static String CUSTOM_SEL_CHANNEL_BG_COLOR = "Channel.sel.customBgColor";
93 private final static boolean DEF_CUSTOM_SEL_CHANNEL_BG_COLOR = false;
94
95 private final static String HL_CHANNEL_BG_COLOR = "Channel.hl.BgColor";
96 private final static int DEF_HL_CHANNEL_BG_COLOR = -1;
97
98 private final static String CUSTOM_HL_CHANNEL_BG_COLOR = "Channel.hl.customBgColor";
99 private final static boolean DEF_CUSTOM_HL_CHANNEL_BG_COLOR = false;
100
101 private final static String VSPLIT_DIVIDER_LOCATION = "VSplit.dividerLocation";
102 private final static int DEF_VSPLIT_DIVIDER_LOCATION = 200;
103
104 private final static String CURRENT_ORCHESTRA_IDX = "OrchestrasPage.currentOrchestraIndex";
105 private final static int DEF_CURRENT_ORCHESTRA_IDX = 0;
106
107 private static Preferences userPrefs = Preferences.userRoot().node(prefNode);
108
109 private final static ClassicPrefs prefs = new ClassicPrefs();
110
111 private
112 ClassicPrefs() { super(prefNode); }
113
114 public static ClassicPrefs
115 preferences() { return prefs; }
116
117 public static Preferences
118 user() { return userPrefs; }
119
120 /**
121 * Gets a string representation of a window's size and location.
122 * The string representation is a comma-separated list
123 * of x and y coordinates, and width and height of the window.
124 * @param window The name of the window whose size and location should be obtained.
125 * @return A string representation of the window's size and location,
126 * or <code>null</code> if the value is not set.
127 */
128 public static String
129 getWindowSizeAndLocation(String window) {
130 return user().get(window + WINDOW_SIZE_AND_LOCATION, DEF_WINDOW_SIZE_AND_LOCATION);
131 }
132
133 /**
134 * Sets the window's size and location.
135 * Use <code>null</code> to remove the current value.
136 * @param window The name of the window whose size and location should be set.
137 * @param s A string representation of the window's size and location.
138 */
139 public static void
140 setWindowSizeAndLocation(String window, String s) {
141 if(s == null) {
142 user().remove(window + WINDOW_SIZE_AND_LOCATION);
143 return;
144 }
145
146 user().put(window + WINDOW_SIZE_AND_LOCATION, s);
147 }
148
149 /**
150 * Determines whether the specified window should be maximized.
151 * @param window The name of the window.
152 * @return <code>true</code> if the specified window should be maximized,
153 * <code>false</code> otherwise.
154 */
155 public static boolean
156 getWindowMaximized(String window) {
157 return user().getBoolean(window + WINDOW_MAXIMIZED, DEF_WINDOW_MAXIMIZED);
158 }
159
160 /**
161 * Sets whether the specified window should be maximized.
162 * @param window The name of the window.
163 * @param b If <code>true</code> the specified window should be maximized.
164 */
165 public static void
166 setWindowMaximized(String window, boolean b) {
167 if(b == getWindowMaximized(window)) return;
168 user().putBoolean(window + WINDOW_MAXIMIZED, b);
169 }
170
171 /**
172 * Gets the divider location of the horizontal split pane.
173 * @return The divider location of the horizontal split pane.
174 */
175 public static int
176 getHSplitDividerLocation() {
177 return user().getInt(HSPLIT_DIVIDER_LOCATION, DEF_HSPLIT_DIVIDER_LOCATION);
178 }
179
180 /**
181 * Sets the divider location of the horizontal split pane.
182 * @param i The new divider location of the horizontal split pane.
183 */
184 public static void
185 setHSplitDividerLocation(int i) {
186 if(i == getHSplitDividerLocation()) return;
187 user().putInt(HSPLIT_DIVIDER_LOCATION, i);
188 }
189
190 /**
191 * Determines whether the window properties (like size and location) should be saved.
192 * @return <code>true</code> if the window properties should be saved,
193 * <code>false</code> otherwise.
194 */
195 public static boolean
196 getSaveWindowProperties() {
197 return user().getBoolean(SAVE_WINDOW_PROPERTIES, DEF_SAVE_WINDOW_PROPERTIES);
198 }
199
200 /**
201 * Sets whether the window properties (like size and location) should be saved.
202 * @param b If <code>true</code> the window properties will be saved.
203 */
204 public static void
205 setSaveWindowProperties(boolean b) {
206 if(b == getSaveWindowProperties()) return;
207 user().putBoolean(SAVE_WINDOW_PROPERTIES, b);
208 }
209
210 /**
211 * Determines whether the Left Pane state should be saved.
212 * @return <code>true</code> if the Left Pane state should be saved,
213 * <code>false</code> otherwise.
214 */
215 public static boolean
216 getSaveLeftPaneState() {
217 return user().getBoolean(SAVE_LEFT_PANE_STATE, DEF_SAVE_LEFT_PANE_STATE);
218 }
219
220 /**
221 * Sets whether the Left Pane state should be saved.
222 * @param b If <code>true</code> the Left Pane state will be saved.
223 */
224 public static void
225 setSaveLeftPaneState(boolean b) {
226 if(b == getSaveLeftPaneState()) return;
227 user().putBoolean(SAVE_LEFT_PANE_STATE, b);
228 }
229
230 /**
231 * Gets the index of the page to be shown in the Left Pane.
232 * @return The index of the page to be shown in the Left Pane.
233 */
234 public static int
235 getLeftPanePageIndex() {
236 return user().getInt(LEFT_PANE_PAGE_IDX, DEF_LEFT_PANE_PAGE_IDX);
237 }
238
239 /**
240 * Sets the maximum number of recent scripts to be kept.
241 * @param i Determines the maximum number of recent scripts to be kept.
242 */
243 public static void
244 setLeftPanePageIndex(int i) {
245 if(i == getLeftPanePageIndex()) return;
246 user().putInt(LEFT_PANE_PAGE_IDX, i);
247 }
248
249 /**
250 * Determines whether the <b>Channels</b> toolbar should be visible.
251 * @return <code>true</code> if the <b>Channels</b> toolbar should be visible,
252 * <code>false</code> otherwise.
253 */
254 public static boolean
255 shouldShowChannelsBar() {
256 return user().getBoolean(SHOW_CHANNELS_BAR, DEF_SHOW_CHANNELS_BAR);
257 }
258
259 /**
260 * Sets whether the <b>Channels</b> toolbar should be visible.
261 * @param b If <code>true</code> the <b>Channels</b> toolbar will be visible at startup.
262 */
263 public static void
264 setShowChannelsBar(boolean b) {
265 if(b == shouldShowChannelsBar()) return;
266 user().putBoolean(SHOW_CHANNELS_BAR, b);
267 }
268
269 /**
270 * Determines whether the statusbar should be visible.
271 * @return <code>true</code> if the statusbar should be visible,
272 * <code>false</code> otherwise.
273 */
274 public static boolean
275 shouldShowStatusbar() { return user().getBoolean(SHOW_STATUSBAR, DEF_SHOW_STATUSBAR); }
276
277 /**
278 * Sets whether the statusbar should be visible.
279 * @param b If <code>true</code> the statusbar will be visible at startup.
280 */
281 public static void
282 setShowStatusbar(boolean b) {
283 if(b == shouldShowStatusbar()) return;
284 user().putBoolean(SHOW_STATUSBAR, b);
285 }
286
287 /**
288 * Determines whether the LS Console should be visible.
289 * @return <code>true</code> if the LS Console should be visible,
290 * <code>false</code> otherwise.
291 */
292 public static boolean
293 shouldShowLSConsole() { return user().getBoolean(SHOW_LS_CONSOLE, DEF_SHOW_LS_CONSOLE); }
294
295 /**
296 * Sets whether the LS Console should be visible.
297 * @param b If <code>true</code> the LS Console will be visible at startup.
298 */
299 public static void
300 setShowLSConsole(boolean b) {
301 if(b == shouldShowLSConsole()) return;
302 user().putBoolean(SHOW_LS_CONSOLE, b);
303 }
304
305 /**
306 * Determines whether the LS Console should be shown in a new window or
307 * docked in the main frame.
308 * @return <code>true</code> if the LS Console should be shown in a new window,
309 * <code>false</code> if the LS Console should be docked in the main frame.
310 */
311 public static boolean
312 isLSConsolePopOut() { return user().getBoolean(LS_CONSOLE_POPOUT, DEF_LS_CONSOLE_POPOUT); }
313
314 /**
315 * Sets whether the LS Console should be shown in a new window or
316 * docked in the main frame.
317 * @param b code>true</code> means that the LS Console will be shown in a new window;
318 * <code>false</code> means that the LS Console will be docked in the main frame.
319 */
320 public static void
321 setLSConsolePopOut(boolean b) {
322 if(b == isLSConsolePopOut()) return;
323 user().putBoolean(LS_CONSOLE_POPOUT, b);
324 }
325
326 /**
327 * Determines whether the left pane should be visible.
328 * @return <code>true</code> if the left pane should be visible,
329 * <code>false</code> otherwise.
330 */
331 public static boolean
332 shouldShowLeftPane() { return user().getBoolean(SHOW_LEFT_PANE, DEF_SHOW_LEFT_PANE); }
333
334 /**
335 * Sets whether the left pane should be visible.
336 * @param b If <code>true</code> the left pane will be visible at startup.
337 */
338 public static void
339 setShowLeftPane(boolean b) {
340 if(b == shouldShowLeftPane()) return;
341 user().putBoolean(SHOW_LEFT_PANE, b);
342 }
343
344 /**
345 * Determines whether the <b>Standard</b> toolbar should be visible.
346 * @return <code>true</code> if the <b>Standard</b> toolbar should be visible,
347 * <code>false</code> otherwise.
348 */
349 public static boolean
350 shouldShowStandardBar() {
351 return user().getBoolean(SHOW_STANDARD_BAR, DEF_SHOW_STANDARD_BAR);
352 }
353
354 /**
355 * Sets whether the <b>Standard</b> toolbar should be visible.
356 * @param b If <code>true</code> the <b>Standard</b> toolbar will be visible at startup.
357 */
358 public static void
359 setShowStandardBar(boolean b) {
360 if(b == shouldShowStandardBar()) return;
361 user().putBoolean(SHOW_STANDARD_BAR, b);
362 }
363
364 /**
365 * Gets the default border color that is used for the selected channels.
366 * @return The default border color that is used for the selected channels.
367 */
368 public static Color
369 getDefaultChannelBorderColor() { return new Color(DEF_CHANNEL_BORDER_COLOR); }
370
371 /**
372 * Gets the custom border color to be used for the selected channels.
373 * @return The custom border color to be used for the selected
374 * channels or <code>null</code> if the color is not specified.
375 */
376 public static Color
377 getChannelBorderColor() {
378 int c = user().getInt(CHANNEL_BORDER_COLOR, DEF_CHANNEL_BORDER_COLOR);
379 return new Color(c);
380 }
381
382 /**
383 * Sets the border color to be used for the selected channels.
384 * Use <code>null</code> to remove the current value.
385 * @param color The border color to be used for the selected channels.
386 */
387 public static void
388 setChannelBorderColor(Color c) {
389 if(c == null) {
390 user().remove(CHANNEL_BORDER_COLOR);
391 return;
392 }
393
394 if(c.getRGB() == getChannelBorderColor().getRGB()) return;
395
396 user().putInt(CHANNEL_BORDER_COLOR, c.getRGB());
397 }
398
399 /**
400 * Determines whether to use a custom border color for the selected channels.
401 * @return <code>true</code> if custom border color must be used
402 * for the selected channels, <code>false</code> otherwise.
403 */
404 public static boolean
405 getCustomChannelBorderColor() {
406 return user().getBoolean (
407 CUSTOM_CHANNEL_BORDER_COLOR, DEF_CUSTOM_CHANNEL_BORDER_COLOR
408 );
409 }
410
411 /**
412 * Sets whether to use a custom border color for the selected channels.
413 * @param b specify <code>true</code> to use a custom border color
414 * for the selected channels, <code>false</code> otherwise.
415 */
416 public static void
417 setCustomChannelBorderColor(boolean b) {
418 if(b == getCustomChannelBorderColor()) return;
419 user().putBoolean(CUSTOM_CHANNEL_BORDER_COLOR, b);
420 }
421
422 /**
423 * Gets the default highlighted border color that
424 * is used when the mouse pointer is over a channel.
425 * @return The default highlighted border color.
426 */
427 public static Color
428 getDefaultChannelBorderHlColor() { return new Color(DEF_CHANNEL_BORDER_HL_COLOR); }
429
430 /**
431 * Gets the custom highlighted border color that
432 * is used when the mouse pointer is over a channel.
433 * @return The custom highlighted border color.
434 */
435 public static Color
436 getChannelBorderHlColor() {
437 int c = user().getInt(CHANNEL_BORDER_HL_COLOR, DEF_CHANNEL_BORDER_HL_COLOR);
438 return new Color(c);
439 }
440
441 /**
442 * Sets the highlighted border color that
443 * is used when the mouse pointer is over a channel.
444 * Use <code>null</code> to remove the current value.
445 * @param color The new highlighted border color.
446 */
447 public static void
448 setChannelBorderHlColor(Color c) {
449 if(c == null) {
450 user().remove(CHANNEL_BORDER_HL_COLOR);
451 return;
452 }
453
454 if(c.getRGB() == getChannelBorderHlColor().getRGB()) return;
455
456 user().putInt(CHANNEL_BORDER_HL_COLOR, c.getRGB());
457 }
458
459 /**
460 * Determines whether to use a custom highlighted border color.
461 * @return <code>true</code> if custom highlighted border color
462 * must be used, <code>false</code> otherwise.
463 */
464 public static boolean
465 getCustomChannelBorderHlColor() {
466 return user().getBoolean (
467 CUSTOM_CHANNEL_BORDER_HL_COLOR, DEF_CUSTOM_CHANNEL_BORDER_HL_COLOR
468 );
469 }
470
471 /**
472 * Sets whether to use a custom highlighted border color.
473 * @param b specify <code>true</code> to use a custom highlighted
474 * border color, <code>false</code> otherwise.
475 */
476 public static void
477 setCustomChannelBorderHlColor(boolean b) {
478 if(b == getCustomChannelBorderHlColor()) return;
479 user().putBoolean(CUSTOM_CHANNEL_BORDER_HL_COLOR, b);
480 }
481
482 /**
483 * Gets the custom background color that
484 * is used when the channel is selected.
485 * @return The custom background color that
486 * is used when the channel is selected.
487 */
488 public static Color
489 getSelectedChannelBgColor() {
490 int c = user().getInt(SEL_CHANNEL_BG_COLOR, DEF_SEL_CHANNEL_BG_COLOR);
491 return c == -1 ? null : new Color(c);
492 }
493
494 /**
495 * Sets the custom background color to
496 * be used when the channel is selected.
497 * Use <code>null</code> to remove the current value.
498 * @param color The new background color to
499 * be used when the channel is selected.
500 */
501 public static void
502 setSelectedChannelBgColor(Color c) {
503 if(c == null) {
504 user().remove(SEL_CHANNEL_BG_COLOR);
505 return;
506 }
507
508 if(getSelectedChannelBgColor() != null) {
509 if(c.getRGB() == getSelectedChannelBgColor().getRGB()) return;
510 }
511
512 user().putInt(SEL_CHANNEL_BG_COLOR, c.getRGB());
513 }
514
515 /**
516 * Determines whether to use a custom background color when a channel is selected.
517 * @return <code>true</code> if custom background color
518 * should be used, <code>false</code> otherwise.
519 */
520 public static boolean
521 getCustomSelectedChannelBgColor() {
522 return user().getBoolean (
523 CUSTOM_SEL_CHANNEL_BG_COLOR, DEF_CUSTOM_SEL_CHANNEL_BG_COLOR
524 );
525 }
526
527 /**
528 * Sets whether to use a custom background color when a channel is selected.
529 * @param b specify <code>true</code> to use a custom
530 * background color, <code>false</code> otherwise.
531 */
532 public static void
533 setCustomSelectedChannelBgColor(boolean b) {
534 if(b == getCustomSelectedChannelBgColor()) return;
535 user().putBoolean(CUSTOM_SEL_CHANNEL_BG_COLOR, b);
536 }
537
538 /**
539 * Gets the custom background color that
540 * is used when the mouse pointer is over a channel.
541 * @return The custom background color that
542 * is used when the mouse pointer is over a channel.
543 */
544 public static Color
545 getHighlightedChannelBgColor() {
546 int c = user().getInt(HL_CHANNEL_BG_COLOR, DEF_HL_CHANNEL_BG_COLOR);
547 return c == -1 ? null : new Color(c);
548 }
549
550 /**
551 * Sets the custom background color to
552 * be used when the mouse pointer is over a channel.
553 * Use <code>null</code> to remove the current value.
554 * @param color The new background color to
555 * be used when the mouse pointer is over a channel.
556 */
557 public static void
558 setHighlightedChannelBgColor(Color c) {
559 if(c == null) {
560 user().remove(HL_CHANNEL_BG_COLOR);
561 return;
562 }
563
564 if(getHighlightedChannelBgColor() != null) {
565 if(c.getRGB() == getHighlightedChannelBgColor().getRGB()) return;
566 }
567
568 user().putInt(HL_CHANNEL_BG_COLOR, c.getRGB());
569 }
570
571 /**
572 * Determines whether to use a custom background
573 * color when the mouse pointer is over a channel.
574 * @return <code>true</code> if custom background color
575 * should be used, <code>false</code> otherwise.
576 */
577 public static boolean
578 getCustomHighlightedChannelBgColor() {
579 return user().getBoolean (
580 CUSTOM_HL_CHANNEL_BG_COLOR, DEF_CUSTOM_HL_CHANNEL_BG_COLOR
581 );
582 }
583
584 /**
585 * Sets whether to use a custom background
586 * color when the mouse pointer is over a channel.
587 * @param b specify <code>true</code> to use a custom
588 * background color, <code>false</code> otherwise.
589 */
590 public static void
591 setCustomHighlightedChannelBgColor(boolean b) {
592 if(b == getCustomHighlightedChannelBgColor()) return;
593 user().putBoolean(CUSTOM_HL_CHANNEL_BG_COLOR, b);
594 }
595
596 /**
597 * Gets the divider location of the vertical split pane.
598 * @return The divider location of the vertical split pane.
599 */
600 public static int
601 getVSplitDividerLocation() {
602 return user().getInt(VSPLIT_DIVIDER_LOCATION, DEF_VSPLIT_DIVIDER_LOCATION);
603 }
604
605 /**
606 * Sets the divider location of the vertical split pane.
607 * @param i The new divider location of the vertical split pane.
608 */
609 public static void
610 setVSplitDividerLocation(int i) {
611 if(i == getVSplitDividerLocation()) return;
612 user().putInt(VSPLIT_DIVIDER_LOCATION, i);
613 }
614
615 /**
616 * Gets the current orchestra index of the last session.
617 * @return The current orchestra index of the last session.
618 */
619 public static int
620 getCurrentOrchestraIndex() {
621 return user().getInt(CURRENT_ORCHESTRA_IDX, DEF_CURRENT_ORCHESTRA_IDX);
622 }
623
624 /**
625 * Sets the current orchestra index.
626 * @param i The orchestra index to be set as current.
627 */
628 public static void
629 setCurrentOrchestraIndex(int i) {
630 if(i == getCurrentOrchestraIndex()) return;
631 user().putInt(CURRENT_ORCHESTRA_IDX, i);
632 }
633
634 public int
635 getDefaultIntValue(String name) {
636 if(name == LS_CONSOLE_BACKGROUND_COLOR) return 0xffffff;
637 if(name == LS_CONSOLE_TEXT_COLOR) return 0x000000;
638 if(name == LS_CONSOLE_NOTIFY_COLOR) return 0xcccccc;
639 if(name == LS_CONSOLE_WARNING_COLOR) return 0x6699ff;
640 if(name == LS_CONSOLE_ERROR_COLOR) return 0xff0000;
641
642 return super.getDefaultIntValue(name);
643 }
644 }

  ViewVC Help
Powered by ViewVC