From c1eb17e8e9746d0fadf7b6dfefcfee599442284f Mon Sep 17 00:00:00 2001 From: sekelsenmat Date: Wed, 28 Mar 2012 13:59:52 +0000 Subject: [PATCH] Finishes the basic implementation of Android native menus git-svn-id: trunk@36394 - --- .../src/com/pascal/lcltest/LCLActivity.java | 27 +++++- examples/androidlcl/mainform.lfm | 11 ++- examples/androidlcl/mainform.pas | 8 ++ lcl/include/menuitem.inc | 2 +- lcl/interfaces/customdrawn/customdrawnint.pas | 5 +- .../customdrawn/customdrawnobject_android.inc | 82 ++++++++++++++----- .../customdrawn/customdrawnwsfactory.pas | 14 ++-- 7 files changed, 113 insertions(+), 36 deletions(-) diff --git a/examples/androidlcl/android/src/com/pascal/lcltest/LCLActivity.java b/examples/androidlcl/android/src/com/pascal/lcltest/LCLActivity.java index 1e166bb488..d8df4701b3 100755 --- a/examples/androidlcl/android/src/com/pascal/lcltest/LCLActivity.java +++ b/examples/androidlcl/android/src/com/pascal/lcltest/LCLActivity.java @@ -160,8 +160,18 @@ public class LCLActivity extends Activity implements SensorEventListener, Locati else { //Log.v("lclproject", "BackKey not going to home"); - return true; } + + // Handling of the Menu hardware key + if (keyCode == KeyEvent.KEYCODE_MENU) + { + flagIsMenuOpen = false; // hard-coding now has a good result, we might change in the future if we ever start getting key events even while the menu is open + if (flagIsMenuOpen) closeOptionsMenu(); + else openOptionsMenu(); + flagIsMenuOpen = !flagIsMenuOpen; + } + + return true; } @Override public boolean onTouchEvent (MotionEvent event) @@ -248,14 +258,22 @@ public class LCLActivity extends Activity implements SensorEventListener, Locati //Log.i("lclapp", "onConfigurationChanged finished"); } + @Override public boolean onCreateOptionsMenu(Menu menu) + { + Log.i("lclapp", "onCreateOptionsMenu"); + return super.onCreateOptionsMenu(menu); + } + @Override public boolean onPrepareOptionsMenu (Menu menu) { + Log.i("lclapp", "onPrepareOptionsMenu"); + super.onPrepareOptionsMenu(menu); int i; // First clear the captions list - for (i = 0; i<6; i++) + for (i = 0; i < lclmenu_captions.length; i++) lclmenu_captions[i] = ""; // Now ask the LCL to fill it @@ -263,15 +281,17 @@ public class LCLActivity extends Activity implements SensorEventListener, Locati // And fill the menus with it menu.clear(); - for (i = 0; i<6; i++) + for (i = 0; i< lclmenu_captions.length; i++) { if (lclmenu_captions[i] != "") { + Log.i("lclapp", "onPrepareOptionsMenu item=" + lclmenu_captions[i]); MenuItem lMenuItem = menu.add(0, i, 0, lclmenu_captions[i]); lMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem item) { + flagIsMenuOpen = false; LCLOnMenuAction(1, item.getItemId()); return true; } @@ -666,6 +686,7 @@ public class LCLActivity extends Activity implements SensorEventListener, Locati public int lclkind; // for the menus public String[] lclmenu_captions = new String[6]; + public boolean flagIsMenuOpen = false; static { diff --git a/examples/androidlcl/mainform.lfm b/examples/androidlcl/mainform.lfm index da64ba0488..da1c3440e9 100644 --- a/examples/androidlcl/mainform.lfm +++ b/examples/androidlcl/mainform.lfm @@ -4,8 +4,9 @@ object Form1: TForm1 Top = 137 Width = 220 Caption = 'Form1' - ClientHeight = 257 + ClientHeight = 230 ClientWidth = 220 + Menu = MainMenu1 OnClick = FormClick OnCreate = FormCreate OnKeyDown = Button1KeyDown @@ -101,4 +102,12 @@ object Form1: TForm1 TabOrder = 7 Text = 'ComboBox1' end + object MainMenu1: TMainMenu + left = 23 + top = 60 + object MenuItem1: TMenuItem + Caption = 'New Item1' + OnClick = MenuItem1Click + end + end end diff --git a/examples/androidlcl/mainform.pas b/examples/androidlcl/mainform.pas index dfcf8dc3ca..a37aa4f385 100644 --- a/examples/androidlcl/mainform.pas +++ b/examples/androidlcl/mainform.pas @@ -22,6 +22,8 @@ type CheckBox1: TCheckBox; ComboBox1: TComboBox; Label1: TLabel; + MainMenu1: TMainMenu; + MenuItem1: TMenuItem; ProgressBar1: TProgressBar; TrackBar1: TTrackBar; procedure Arrow1Click(Sender: TObject); @@ -44,6 +46,7 @@ type procedure FormCreate(Sender: TObject); procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure FormPaint(Sender: TObject); + procedure MenuItem1Click(Sender: TObject); private { private declarations } public @@ -234,6 +237,11 @@ begin Canvas.Rectangle(200, 200, 300, 300);} end; +procedure TForm1.MenuItem1Click(Sender: TObject); +begin + DebugLn('[TForm1.MenuItem1Click]'); +end; + procedure TForm1.HandleMessageDialogFinished(Sender: TObject; AResult: Integer); begin DebugLn(Format('[TForm1.HandleMessageDialogFinished] AResult=%d', [AResult])); diff --git a/lcl/include/menuitem.inc b/lcl/include/menuitem.inc index c0c2a0dbbd..9292800987 100644 --- a/lcl/include/menuitem.inc +++ b/lcl/include/menuitem.inc @@ -131,7 +131,7 @@ begin //DebugLn('TMenuItem.CreateHandle ',dbgsName(Self),' ',dbgs(Self)); //DebugLn('TMenuItem.CreateHandle START ',Name,':',ClassName); if not FVisible then RaiseGDBException(''); - Handle := TWSMenuItemClass(WidgetSetClass).CreateHandle(Self); + FHandle := TWSMenuItemClass(WidgetSetClass).CreateHandle(Self); CheckChildrenHandles; if Parent <> nil then diff --git a/lcl/interfaces/customdrawn/customdrawnint.pas b/lcl/interfaces/customdrawn/customdrawnint.pas index e2c0f08251..620eab7eb0 100644 --- a/lcl/interfaces/customdrawn/customdrawnint.pas +++ b/lcl/interfaces/customdrawn/customdrawnint.pas @@ -320,7 +320,7 @@ function Java_com_pascal_lclproject_LCLActivity_LCLOnConfigurationChanged( function Java_com_pascal_lclproject_LCLActivity_LCLOnSensorChanged( env:PJNIEnv; this:jobject; ASensorKind: jint; AValues: JDoubleArray): jint; cdecl; function Java_com_pascal_lclproject_LCLActivity_LCLOnMenuAction( - env:PJNIEnv; this:jobject; kind: jint; itemIndex: jint): jint; cdecl; + env:PJNIEnv; this:jobject; kind, itemIndex: jint): jint; cdecl; function JNI_OnLoad(vm:PJavaVM;reserved:pointer):jint; cdecl; procedure JNI_OnUnload(vm:PJavaVM;reserved:pointer); cdecl; @@ -332,10 +332,11 @@ var // Other classes and objects javaAndroidAppActivityClass: JClass = nil; - javaJavaLandSystemClass: JClass = nil; + javaJavaLangSystemClass: JClass = nil; javaAndroidOSBuildClass: JClass = nil; javaAndroidOSVibratorClass: JClass = nil; javaAndroidContentContextClass: JClass = nil; + javaJavaLangStringClass: JClass = nil; // Fields of our Activity // Strings diff --git a/lcl/interfaces/customdrawn/customdrawnobject_android.inc b/lcl/interfaces/customdrawn/customdrawnobject_android.inc index 40da1598d6..d8fd19ab90 100644 --- a/lcl/interfaces/customdrawn/customdrawnobject_android.inc +++ b/lcl/interfaces/customdrawn/customdrawnobject_android.inc @@ -335,36 +335,79 @@ begin end; function Java_com_pascal_lclproject_LCLActivity_LCLOnMenuAction( - env:PJNIEnv; this:jobject; kind: jint; itemIndex: jint): jint; cdecl; + env:PJNIEnv; this:jobject; kind, itemIndex: jint): jint; cdecl; var javaField_lclmenu_captions: jfieldid; - javaObject_lclmenu_captions: jobject; + javaObject_lclmenu_captions: jobjectarray; lJavaString: jstring; lCurrentForm: TCDNonNativeForm; lMenu: TMainMenu; + StrPas: string; Str: PChar; lMenuItem: TMenuItem; - i, CurIndex: Integer; + i, CurIndex, NumMenuItems: Integer; begin Result := 0; //{$ifdef VerboseCDEvents} - __android_log_write(ANDROID_LOG_INFO,'lclapp',PChar( - Format('LCLOnMenuAction called kind=%d itemIndex=%d', [kind, itemIndex]))); + DebugLn(Format('LCLOnMenuAction called kind=%d itemIndex=%d', [kind, itemIndex])); //{$endif} if (javaEnvRef = nil) then Exit; + lCurrentForm := GetCurrentForm(); + if lCurrentForm = nil then Exit; + lMenu := lCurrentForm.LCLForm.Menu; + if lMenu = nil then Exit; + // kind=0 means that we should create the menu items list if kind = 0 then begin - lCurrentForm := GetCurrentForm(); - if lCurrentForm = nil then Exit; - lMenu := lCurrentForm.LCLForm.Menu; - if lMenu = nil then Exit; + // First calculate the number of menu items + NumMenuItems := 0; + for i := 0 to lMenu.Items.Count-1 do + begin + lMenuItem := lMenu.Items[i]; + // Various things might make a menu item invalid and therefore not part of the list + if not lMenuItem.Visible then Continue; + if lMenuItem.Caption = '-' then Continue; + Inc(NumMenuItems); + end; + // Now fill the items javaField_lclmenu_captions := javaEnvRef^^.GetFieldID(javaEnvRef, javaActivityClass, 'lclmenu_captions', '[Ljava/lang/String;'); - javaObject_lclmenu_captions := javaEnvRef^^.GetObjectField(javaEnvRef, javaActivityClass, javaField_lclmenu_captions); +// javaObject_lclmenu_captions := javaEnvRef^^.GetObjectField(javaEnvRef, javaActivityClass, javaField_lclmenu_captions); + javaObject_lclmenu_captions := javaEnvRef^^.NewObjectArray(javaEnvRef, NumMenuItems, + javaJavaLangStringClass, javaEnvRef^^.NewStringUTF(javaEnvRef, '')); +// DebugLn(Format('LCLOnMenuAction lclmenu_captions field=%x object=%x', [PtrUInt(javaField_lclmenu_captions), PtrUInt(javaObject_lclmenu_captions)])); + CurIndex := 0; + StrPas := ''; + for i := 0 to lMenu.Items.Count-1 do + begin + DebugLn(Format('LCLOnMenuAction item=%d', [i])); + lMenuItem := lMenu.Items[i]; + // Various things might make a menu item invalid and therefore not part of the list + if not lMenuItem.Visible then Continue; + if lMenuItem.Caption = '-' then Continue; + + StrPas := lMenuItem.Caption; + Str := PChar(StrPas); + lJavaString := javaEnvRef^^.NewStringUTF(javaEnvRef, Str); + DebugLn(Format('LCLOnMenuAction lJavaString=%x Str=%s', [PtrUInt(lJavaString), StrPas])); + javaEnvRef^^.SetObjectArrayElement(javaEnvRef, javaObject_lclmenu_captions, CurIndex, lJavaString); + javaEnvRef^^.DeleteLocalRef(javaEnvRef, str); + + Inc(CurIndex); + + if CurIndex >= NumMenuItems then Break; + end; + + javaEnvRef^^.SetObjectField(javaEnvRef, javaActivityObject, javaField_lclmenu_captions, javaObject_lclmenu_captions); + end + // kind=1 means a button click event + else + begin + // Searched for the clicked item CurIndex := 0; for i := 0 to lMenu.Items.Count-1 do begin @@ -373,23 +416,17 @@ begin if not lMenuItem.Visible then Continue; if lMenuItem.Caption = '-' then Continue; - Str := PChar(lMenuItem.Caption); - lJavaString :=javaEnvRef^^.NewStringUTF(javaEnvRef, Str); - javaEnvRef^^.SetObjectArrayElement(javaEnvRef, javaObject_lclmenu_captions, CurIndex, lJavaString); + if itemIndex = CurIndex then Break; Inc(CurIndex); - - if CurIndex >= 6 then Break; end; - end - // kind=1 means a button click event - else - begin + lMenuItem.Click(); end; // This sends messages like Invalidate requests Result := eventResult; + DebugLn('Fim'); end; const NativeMethods: array[0..8] of JNINativeMethod= @@ -451,10 +488,11 @@ begin end; // Now other classes javaAndroidAppActivityClass := javaEnvRef^^.FindClass(javaEnvRef,'android/app/Activity'); - javaJavaLandSystemClass := javaEnvRef^^.FindClass(javaEnvRef,'java/lang/System'); + javaJavaLangSystemClass := javaEnvRef^^.FindClass(javaEnvRef,'java/lang/System'); javaAndroidOSBuildClass := javaEnvRef^^.FindClass(javaEnvRef,'android/os/Build'); javaAndroidOSVibratorClass := javaEnvRef^^.FindClass(javaEnvRef,'android/os/Vibrator'); javaAndroidContentContextClass := javaEnvRef^^.FindClass(javaEnvRef,'android/content/Context'); + javaJavaLangStringClass := javaEnvRef^^.FindClass(javaEnvRef,'java/lang/String'); // Register Pascal exported calls if javaEnvRef^^.RegisterNatives(javaEnvRef, javaActivityClass, @NativeMethods[0],length(NativeMethods))<0 then @@ -522,7 +560,7 @@ begin // Methods from android.app.Activity javaMethod_Activity_finish := javaEnvRef^^.GetMethodID(javaEnvRef, javaAndroidAppActivityClass, 'finish', '()V'); // Methods from java.lang.System - javaMethod_System_exit := javaEnvRef^^.GetStaticMethodID(javaEnvRef, javaJavaLandSystemClass, 'exit', '(I)V'); + javaMethod_System_exit := javaEnvRef^^.GetStaticMethodID(javaEnvRef, javaJavaLangSystemClass, 'exit', '(I)V'); // Generic methods from Context javaMethod_getSystemService := javaEnvRef^^.GetMethodID(javaEnvRef, javaAndroidContentContextClass, 'getSystemService', '(Ljava/lang/String;)Ljava/lang/Object;'); @@ -1038,7 +1076,7 @@ begin // Call the method lParams[0].i := 0; - javaEnvRef^^.CallStaticVoidMethodA(javaEnvRef, javaJavaLandSystemClass, javaMethod_System_exit, @lParams[0]); + javaEnvRef^^.CallStaticVoidMethodA(javaEnvRef, javaJavaLangSystemClass, javaMethod_System_exit, @lParams[0]); DebugLn('[TCDWidgetSet.AppTerminate] End'); end; diff --git a/lcl/interfaces/customdrawn/customdrawnwsfactory.pas b/lcl/interfaces/customdrawn/customdrawnwsfactory.pas index b085fc5665..bbcda70d34 100644 --- a/lcl/interfaces/customdrawn/customdrawnwsfactory.pas +++ b/lcl/interfaces/customdrawn/customdrawnwsfactory.pas @@ -111,8 +111,8 @@ uses { WinCEWSDialogs,} CustomDrawnWSExtCtrls, CustomDrawnWSForms, -{ WinCEWSImgList, - WinCEWSMenus,} +// WinCEWSImgList, + CustomDrawnWSMenus, CustomDrawnWSSpin, CustomDrawnWSStdCtrls, CustomDrawnWSLazDeviceAPIs{, @@ -513,14 +513,14 @@ end; // Menus function RegisterMenuItem: Boolean; alias : 'WSRegisterMenuItem'; begin -// RegisterWSComponent(TMenuItem, TWinCEWSMenuItem); - Result := False; + RegisterWSComponent(TMenuItem, TCDWSMenuItem); + Result := True; end; function RegisterMenu: Boolean; alias : 'WSRegisterMenu'; begin -// RegisterWSComponent(TMenu, TWinCEWSMenu); - Result := False; + RegisterWSComponent(TMenu, TCDWSMenu); + Result := True; end; function RegisterMainMenu: Boolean; alias : 'WSRegisterMainMenu'; @@ -530,7 +530,7 @@ end; function RegisterPopupMenu: Boolean; alias : 'WSRegisterPopupMenu'; begin -// RegisterWSComponent(TPopupMenu, TWinCEWSPopupMenu); +// RegisterWSComponent(TPopupMenu, TCDWSPopupMenu); Result := False; end;