Author: manolo
Date: 2013-02-05 07:40:17 -0800 (Tue, 05 Feb 2013)
New Revision: 9813
Log:
Mac OS: internationalization support for application menu, and more text input.
Modified:
branches/branch-3.0/documentation/src/osissues.dox
branches/branch-3.0/include/fltk3/osx.h
branches/branch-3.0/src/fltk3/cocoa.mm
branches/branch-3.0/src/fltk3/run.cxx
Modified: branches/branch-3.0/documentation/src/osissues.dox
===================================================================
--- branches/branch-3.0/documentation/src/osissues.dox 2013-02-02 15:46:00 UTC
(rev 9812)
+++ branches/branch-3.0/documentation/src/osissues.dox 2013-02-05 15:40:17 UTC
(rev 9813)
@@ -716,10 +716,6 @@
Attaches the callback \c cb to the "About myprog" item of the system
application menu.
\c cb will be called with NULL first argument and \c user_data second argument.
-Fl_Mac_App_Menu class
-\par
-The Fl_Mac_App_Menu class allows to localize the application menu.
-
Fl_Sys_Menu_Bar class
\par
@@ -727,8 +723,8 @@
placed in the system menu bar (at top-left of display), and, on other
platforms,
at a user-chosen location of a user-chosen window.
+
\subsection osissues_quartz Drawing Things Using Quartz
-
All code inside Fl_Widget::draw()
is expected to call Quartz drawing functions. The Quartz coordinate system
is flipped to match
@@ -737,6 +733,27 @@
\c fl_gc is the appropriate Quartz 2D drawing environment.
Include FL/x.H to declare the \c fl_gc variable.
+\subsection osissues_localize Internationalization
+All FLTK programs contain an application menu with, e.g., the About xxx, Hide
xxx, and Quit xxx items.
+This menu can be internationalized/localized by any of two means.
+\li using the Fl_Mac_App_Menu class.
+\li using the standard Mac OS X localization procedure. Create a
language-specific .lproj directory
+(e.g., <tt>German.lproj</tt>) in the Resources subdirectory of the application
bundle.
+Create therein a <tt>Localizable.strings</tt> file that translates all menu
items to this language.
+The German <tt>Localizable.strings</tt> file, for example, contains:
+\verbatim
+"About %@" = "Über %@";
+"Print Front Window"="Frontfenster drucken";
+"Services" = "Dienste";
+"Hide %@"="%@ ausblenden";
+"Hide Others"="Andere ausblenden";
+"Show All"="Alle einblenden";
+"Quit %@"="%@ beenden";
+\endverbatim
+Set <tt>"Print Front Window" = "";</tt> therein so the application menu
doesn't show a "Print Front Window" item.
+To localize the application name itself, create a file
<tt>InfoPlist.strings</tt> in each .lproj directory
+and put <tt>CFBundleName = "localized name";</tt> in each such file.
+
Fl_Double_Window
OS X double-buffers all windows automatically. On OS X,
Modified: branches/branch-3.0/include/fltk3/osx.h
===================================================================
--- branches/branch-3.0/include/fltk3/osx.h 2013-02-02 15:46:00 UTC (rev
9812)
+++ branches/branch-3.0/include/fltk3/osx.h 2013-02-05 15:40:17 UTC (rev
9813)
@@ -200,6 +200,7 @@
/** \defgroup group_macosx Mac OS X-specific symbols
Mac OS X-specific symbols declared in <fltk3/x.h> or <fltk3/gl.h>
+ \sa \ref osissues_macos
@{ */
/** @brief Register a function called for each file dropped onto an
application icon.
Modified: branches/branch-3.0/src/fltk3/cocoa.mm
===================================================================
--- branches/branch-3.0/src/fltk3/cocoa.mm 2013-02-02 15:46:00 UTC (rev
9812)
+++ branches/branch-3.0/src/fltk3/cocoa.mm 2013-02-05 15:40:17 UTC (rev
9813)
@@ -1608,6 +1608,13 @@
When the character palette is used to enter text, the system sends an
insertText: message to myview. The code processes it
as an fltk3::PASTE event. The in_key_event field of the FLView class allows
to differentiate keyboard from palette inputs.
+ During processing of the handleEvent message, inserted and marked strings are
concatenated in a single string
+ inserted in a single fltk3::KEYBOARD event after return from handleEvent. The
need_handle member variable of FLView allows
+ to determine when setMarkedText or insertText strings have been sent during
handleEvent processing, and therefore
+ an fltk3::KEYBOARD event is needed. Concatenating two insertText operations
or an insertText followed by a setMarkedText is possible.
+ In contrast, setMarkedText followed by insertText or by another setMarkedText
isn't correct if concatenated in a single
+ string. Thus, in such case, the setMarkedText and the next operation produce
each an fltk3::KEYBOARD event.
+
OS >= 10.7 contains a feature where pressing and holding certain keys opens a
menu window that shows a list
of possible accented variants of this key. The selectedRange field of the
FLView class and the selectedRange, insertText:
and setMarkedText: methods of the NSTextInputClient protocol are used to
support this feature.
@@ -1705,11 +1712,13 @@
#endif
> {
@private
- BOOL in_key_event;
+ BOOL in_key_event; // YES means keypress is being processed by handleEvent
+ BOOL need_handle; // YES means fltk3::handle(fltk3::KEYBOARD,) is needed
after handleEvent processing
NSInteger identifier;
NSRange selectedRange;
}
+ (void)prepareEtext:(NSString*)aString;
++ (void)concatEtext:(NSString*)aString;
- (id)init;
- (void)drawRect:(NSRect)rect;
- (BOOL)acceptsFirstResponder;
@@ -1785,7 +1794,9 @@
}
else {
in_key_event = YES;
+ need_handle = NO;
handled = [[self performSelector:inputContextSEL] handleEvent:theEvent];
+ if (need_handle) handled = fltk3::handle(fltk3::KEYBOARD,
[(FLWindow*)[theEvent window] getFl_Window]);
in_key_event = NO;
}
fl_unlock_function();
@@ -1837,7 +1848,9 @@
fltk3::first_window(window);
cocoaKeyboardHandler(theEvent);
in_key_event = YES;
+ need_handle = NO;
[[self performSelector:inputContextSEL] handleEvent:theEvent];
+ if (need_handle) fltk3::handle(fltk3::KEYBOARD, window);
in_key_event = NO;
fl_unlock_function();
}
@@ -1995,6 +2008,12 @@
fltk3::e_length = l;
}
++ (void)concatEtext:(NSString*)aString {
+ // extends fltk3::e_text with aString
+ NSString *newstring = [[NSString stringWithUTF8String:fltk3::e_text]
stringByAppendingString:aString];
+ [FLView prepareEtext:newstring];
+}
+
- (void)doCommandBySelector:(SEL)aSelector {
//NSLog(@"doCommandBySelector:%s",sel_getName(aSelector));
[FLView prepareEtext:[[NSApp currentEvent] characters]];
@@ -2023,12 +2042,19 @@
fltk3::handle(fltk3::KEYBOARD, target);
fltk3::e_keysym = saved_keysym;
}
- [FLView prepareEtext:received];
+ if (in_key_event && Fl_X::next_marked_length && fltk3::e_length) {
+ // if setMarkedText + insertText is sent during handleEvent, text cannot
be concatenated in single fltk3::KEYBOARD event
+ fltk3::handle(fltk3::KEYBOARD, target);
+ fltk3::e_length = 0;
+ }
+ if (in_key_event && fltk3::e_length) [FLView concatEtext:received];
+ else [FLView prepareEtext:received];
// We can get called outside of key events (e.g., from the character
palette, from CJK text input).
// Transform character palette actions to fltk3::PASTE events.
Fl_X::next_marked_length = 0;
int flevent = (in_key_event || fltk3::marked_text_length()) ?
fltk3::KEYBOARD : fltk3::PASTE;
- fltk3::handle( flevent, target);
+ if (!in_key_event) fltk3::handle( flevent, target);
+ else need_handle = YES;
selectedRange = NSMakeRange(100, 0); // 100 is an arbitrary value
// for some reason, with the palette, the window does not redraw until the
next mouse move or button push
// sending a 'redraw()' or 'awake()' does not solve the issue!
@@ -2060,9 +2086,16 @@
fltk3::handle(fltk3::KEYBOARD, target);
fltk3::e_keysym = 'a'; // pretend a letter key was hit
}
- [FLView prepareEtext:received];
- Fl_X::next_marked_length = fltk3::e_length;
- fltk3::handle(fltk3::KEYBOARD, target);
+ if (in_key_event && Fl_X::next_marked_length && fltk3::e_length) {
+ // if setMarkedText + setMarkedText is sent during handleEvent, text
cannot be concatenated in single fltk3::KEYBOARD event
+ fltk3::handle(fltk3::KEYBOARD, target);
+ fltk3::e_length = 0;
+ }
+ if (in_key_event && fltk3::e_length) [FLView concatEtext:received];
+ else [FLView prepareEtext:received];
+ Fl_X::next_marked_length = strlen([received UTF8String]);
+ if (!in_key_event) fltk3::handle( fltk3::KEYBOARD, target);
+ else need_handle = YES;
selectedRange = NSMakeRange(100, newSelection.length);
fl_unlock_function();
}
@@ -3039,20 +3072,22 @@
NSMenuItem *menuItem;
NSString *title;
- NSString *nsappname = [[[NSBundle mainBundle] infoDictionary]
objectForKey:@"CFBundleName"];
+ SEL infodictSEL = (fl_mac_os_version >= 100200 ?
@selector(localizedInfoDictionary) : @selector(infoDictionary));
+ NSString *nsappname = [[[NSBundle mainBundle] performSelector:infodictSEL]
objectForKey:@"CFBundleName"];
if (nsappname == nil)
nsappname = [[NSProcessInfo processInfo] processName];
appleMenu = [[NSMenu alloc] initWithTitle:@""];
/* Add menu items */
- title = [[NSString stringWithUTF8String:Fl_Mac_App_Menu::about]
stringByAppendingString:nsappname];
+ title = [NSString stringWithFormat:NSLocalizedString([NSString
stringWithUTF8String:Fl_Mac_App_Menu::about],nil), nsappname];
menuItem = [appleMenu addItemWithTitle:title action:@selector(showPanel)
keyEquivalent:@""];
FLaboutItemTarget *about = [[FLaboutItemTarget alloc] init];
[menuItem setTarget:about];
[appleMenu addItem:[NSMenuItem separatorItem]];
// Print front window
- if (strlen(Fl_Mac_App_Menu::print) > 0) {
+ title = NSLocalizedString([NSString
stringWithUTF8String:Fl_Mac_App_Menu::print], nil);
+ if ([title length] > 0) {
menuItem = [appleMenu
- addItemWithTitle:[NSString
stringWithUTF8String:Fl_Mac_App_Menu::print]
+ addItemWithTitle:title
action:@selector(printPanel)
keyEquivalent:@""];
[menuItem setTarget:about];
@@ -3064,29 +3099,29 @@
// Services Menu
services = [[NSMenu alloc] init];
menuItem = [appleMenu
- addItemWithTitle:[NSString
stringWithUTF8String:Fl_Mac_App_Menu::services]
+ addItemWithTitle:NSLocalizedString([NSString
stringWithUTF8String:Fl_Mac_App_Menu::services], nil)
action:nil
keyEquivalent:@""];
[appleMenu setSubmenu:services forItem:menuItem];
[appleMenu addItem:[NSMenuItem separatorItem]];
// Hide AppName
- title = [[NSString stringWithUTF8String:Fl_Mac_App_Menu::hide]
stringByAppendingString:nsappname];
+ title = [NSString stringWithFormat:NSLocalizedString([NSString
stringWithUTF8String:Fl_Mac_App_Menu::hide],nil), nsappname];
[appleMenu addItemWithTitle:title
action:@selector(hide:)
keyEquivalent:@"h"];
// Hide Others
menuItem = [appleMenu
- addItemWithTitle:[NSString
stringWithUTF8String:Fl_Mac_App_Menu::hide_others]
+ addItemWithTitle:NSLocalizedString([NSString
stringWithUTF8String:Fl_Mac_App_Menu::hide_others] , nil)
action:@selector(hideOtherApplications:)
keyEquivalent:@"h"];
[menuItem
setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
// Show All
- [appleMenu addItemWithTitle:[NSString
stringWithUTF8String:Fl_Mac_App_Menu::show]
+ [appleMenu addItemWithTitle:NSLocalizedString([NSString
stringWithUTF8String:Fl_Mac_App_Menu::show] , nil)
action:@selector(unhideAllApplications:)
keyEquivalent:@""];
[appleMenu addItem:[NSMenuItem separatorItem]];
// Quit AppName
- title = [[NSString stringWithUTF8String:Fl_Mac_App_Menu::quit]
- stringByAppendingString:nsappname];
+ title = [NSString stringWithFormat:NSLocalizedString([NSString
stringWithUTF8String:Fl_Mac_App_Menu::quit] , nil),
+ nsappname];
[appleMenu addItemWithTitle:title
action:@selector(terminate:)
keyEquivalent:@"q"];
Modified: branches/branch-3.0/src/fltk3/run.cxx
===================================================================
--- branches/branch-3.0/src/fltk3/run.cxx 2013-02-02 15:46:00 UTC (rev
9812)
+++ branches/branch-3.0/src/fltk3/run.cxx 2013-02-05 15:40:17 UTC (rev
9813)
@@ -84,13 +84,13 @@
// Globals...
//
#if defined(__APPLE__) || defined(FLTK3_DOXYGEN)
-const char *Fl_Mac_App_Menu::about = "About ";
+const char *Fl_Mac_App_Menu::about = "About %@";
const char *Fl_Mac_App_Menu::print = "Print Front Window";
const char *Fl_Mac_App_Menu::services = "Services";
-const char *Fl_Mac_App_Menu::hide = "Hide ";
+const char *Fl_Mac_App_Menu::hide = "Hide %@";
const char *Fl_Mac_App_Menu::hide_others = "Hide Others";
const char *Fl_Mac_App_Menu::show = "Show All";
-const char *Fl_Mac_App_Menu::quit = "Quit ";
+const char *Fl_Mac_App_Menu::quit = "Quit %@";
#endif // __APPLE__
#ifndef FLTK3_DOXYGEN
fltk3::Widget *fltk3::belowmouse_,
_______________________________________________
fltk-commit mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-commit