rhodes 2.0.0.beta1 → 2.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. data/CHANGELOG +5 -0
  2. data/LICENSE +19 -674
  3. data/Manifest.txt +21 -4
  4. data/README.textile +5 -36
  5. data/Rakefile +5 -0
  6. data/lib/build/jake.rb +3 -1
  7. data/lib/extensions/rexml/rexml/document.rb +2 -0
  8. data/lib/extensions/rexml/rexml/parsers/baseparser.rb +0 -6
  9. data/lib/extensions/rhoxml/rexml/child.rb +96 -0
  10. data/lib/extensions/rhoxml/rexml/document.rb +527 -0
  11. data/lib/extensions/rhoxml/rexml/element.rb +987 -0
  12. data/lib/extensions/rhoxml/rexml/encoding.rb +71 -0
  13. data/lib/extensions/rhoxml/rexml/encodings/US-ASCII.rb +30 -0
  14. data/lib/extensions/rhoxml/rexml/encodings/UTF-16.rb +35 -0
  15. data/lib/extensions/rhoxml/rexml/encodings/UTF-8.rb +18 -0
  16. data/lib/extensions/rhoxml/rexml/namespace.rb +47 -0
  17. data/lib/extensions/rhoxml/rexml/node.rb +76 -0
  18. data/lib/extensions/rhoxml/rexml/parent.rb +166 -0
  19. data/lib/extensions/rhoxml/rexml/parseexception.rb +51 -0
  20. data/lib/extensions/rhoxml/rexml/parsers/baseparser.rb +531 -0
  21. data/lib/extensions/rhoxml/rexml/parsers/treeparser.rb +100 -0
  22. data/lib/extensions/rhoxml/rexml/parsers/xpathparser.rb +698 -0
  23. data/lib/extensions/rhoxml/rexml/set.rb +1274 -0
  24. data/lib/extensions/rhoxml/rexml/source.rb +258 -0
  25. data/lib/extensions/rhoxml/rexml/xmltokens.rb +18 -0
  26. data/lib/extensions/rhoxml/rexml/xpath.rb +77 -0
  27. data/lib/extensions/rhoxml/rexml/xpath_parser.rb +806 -0
  28. data/lib/framework/builtinME.rb +2 -0
  29. data/lib/framework/dateME.rb +5 -1
  30. data/lib/framework/rho/render.rb +10 -2
  31. data/lib/framework/rhom/rhom_object_factory.rb +2 -1
  32. data/lib/framework/singleton.rb +1 -1
  33. data/platform/android/Rhodes/jni/src/rhodes.cpp +2 -4
  34. data/platform/android/Rhodes/src/com/rhomobile/rhodes/NativeBar.java +23 -18
  35. data/platform/android/Rhodes/src/com/rhomobile/rhodes/Rhodes.java +42 -69
  36. data/platform/android/Rhodes/src/com/rhomobile/rhodes/SplashScreen.java +59 -7
  37. data/platform/android/Rhodes/src/com/rhomobile/rhodes/camera/Camera.java +1 -1
  38. data/platform/android/Rhodes/src/com/rhomobile/rhodes/mapview/Annotation.java +1 -0
  39. data/platform/android/Rhodes/src/com/rhomobile/rhodes/mapview/MapView.java +97 -85
  40. data/platform/android/Rhodes/src/com/rhomobile/rhodes/uri/SmsUriHandler.java +52 -0
  41. data/platform/android/build/RhodesSRC_build.files +1 -0
  42. data/platform/android/build/android.rake +38 -14
  43. data/platform/bb/RubyVM/RubyVM.jdp +1 -0
  44. data/platform/bb/build/RubyVM_build.files +1 -0
  45. data/platform/bb/build/bb.rake +44 -2
  46. data/platform/bb/rhodes/platform/5.0/com/rho/BrowserAdapter5.java +1 -1
  47. data/platform/bb/rhodes/rhodes.jdp +4 -4
  48. data/platform/bb/rhodes/src/com/rho/BrowserAdapter.java +8 -4
  49. data/platform/bb/rhodes/src/com/rho/rubyext/Alert.java +149 -17
  50. data/platform/bb/rhodes/src/rhomobile/PushListeningThread.java +20 -17
  51. data/platform/bb/rhodes/src/rhomobile/RhodesApplication.java +54 -28
  52. data/platform/bb/rhodes/src/rhomobile/mapview/Annotation.java +1 -0
  53. data/platform/bb/rhodes/src/rhomobile/mapview/GoogleMapField.java +37 -11
  54. data/platform/bb/rhodes/src/rhomobile/mapview/MapView.java +49 -19
  55. data/platform/bb/rhodes/src/rhomobile/mapview/MapViewScreen.java +6 -0
  56. data/platform/iphone/Classes/MapView/GoogleGeocoder.h +6 -7
  57. data/platform/iphone/Classes/MapView/GoogleGeocoder.m +70 -70
  58. data/platform/iphone/Classes/MapView/MapAnnotation.h +5 -3
  59. data/platform/iphone/Classes/MapView/MapAnnotation.m +10 -8
  60. data/platform/iphone/Classes/MapView/MapViewController.h +13 -10
  61. data/platform/iphone/Classes/MapView/MapViewController.m +131 -72
  62. data/platform/iphone/Classes/Rhodes.h +2 -0
  63. data/platform/iphone/Classes/Rhodes.m +13 -1
  64. data/platform/iphone/Classes/SimpleMainView.m +0 -1
  65. data/platform/iphone/Classes/TabbedMainView.m +5 -6
  66. data/platform/shared/common/RhoTime.h +2 -2
  67. data/platform/shared/common/RhodesApp.cpp +1 -1
  68. data/platform/shared/db/DBAdapter.cpp +6 -0
  69. data/platform/shared/net/CURLNetRequest.cpp +23 -1
  70. data/platform/shared/ruby/thread_win32.c +9 -1
  71. data/platform/shared/rubyJVM/src/com/rho/Capabilities.java +6 -0
  72. data/platform/shared/rubyJVM/src/com/rho/RhodesApp.java +1 -1
  73. data/platform/shared/rubyJVM/src/com/rho/sync/ClientRegister.java +1 -1
  74. data/platform/shared/rubyJVM/src/com/xruby/GeneratedMethods/RubySymbol_Methods.java +6 -1
  75. data/platform/shared/rubyJVM/src/com/xruby/GeneratedMethods/RubyTime_Methods.java +3 -3
  76. data/platform/shared/rubyJVM/src/com/xruby/runtime/builtin/InputStreamExecutor.java +1 -1
  77. data/platform/shared/rubyJVM/src/com/xruby/runtime/builtin/RubyArray.java +15 -3
  78. data/platform/shared/rubyJVM/src/com/xruby/runtime/builtin/RubyString.java +10 -2
  79. data/platform/shared/rubyJVM/src/com/xruby/runtime/builtin/RubyTime.java +12 -1
  80. data/platform/shared/rubyJVM/src/com/xruby/runtime/lang/RubyKernelModule.java +18 -9
  81. data/platform/shared/rubyJVM/src/com/xruby/runtime/lang/RubySymbol.java +5 -0
  82. data/platform/shared/rubyJVM/src/org/json/me/JSONArray.java +2 -1
  83. data/platform/shared/unzip/unzip.cpp +1 -1
  84. data/platform/wm/build/wm.rake +27 -6
  85. data/platform/wm/rhodes/Alert.cpp +335 -5
  86. data/platform/wm/rhodes/Alert.h +84 -1
  87. data/platform/wm/rhodes/MainWindow.cpp +28 -6
  88. data/platform/wm/rhodes/MainWindow.h +7 -2
  89. data/platform/wm/rhodes/Rhodes.cpp +23 -0
  90. data/platform/wm/rhodes/rho/rubyext/SystemImpl.cpp +2 -1
  91. data/platform/wm/rhodes/stdafx.h +1 -0
  92. data/platform/wm/tools/detool/detool.cpp +405 -14
  93. data/rakefile.rb +5 -0
  94. data/res/build-tools/detool.exe +0 -0
  95. data/res/generators/rhogen.rb +2 -0
  96. data/rhodes.gemspec +1 -1
  97. data/spec/framework_spec/app/spec/fixtures/object_values.txt +1 -1
  98. data/spec/framework_spec/app/spec/pagination/fixtures/object_values.txt +1 -1
  99. data/spec/framework_spec/app/spec/rhom_object_spec.rb +12 -12
  100. metadata +23 -6
  101. data/LICENSING_OPTIONS +0 -1
  102. data/platform/bb/build/rhodesApp.rapc +0 -9
  103. data/res/generators/templates/source/source_adapter.rb +0 -48
  104. data/rhobuild.yml +0 -37
@@ -385,10 +385,18 @@ static void
385
385
  native_cond_wait(rb_thread_cond_t *cond, rb_thread_lock_t *mutex)
386
386
  {
387
387
  DWORD r;
388
+ DWORD dwErr = 0;
388
389
  struct cond_event_entry entry;
390
+ //WinMo BUG: in release mode CreateEventW without name inside non-main thread does not work
391
+ static int nCounter = 0;
392
+ wchar_t buf[20];
393
+ wsprintfW(buf, L"REvent%d", nCounter);
394
+ nCounter = nCounter + 1;
389
395
 
390
396
  entry.next = 0;
391
- entry.event = CreateEvent(0, FALSE, FALSE, 0);
397
+ entry.event = CreateEventW(0, FALSE, FALSE, buf);
398
+ // dwErr = GetLastError();
399
+ // printf("CreateEvent: %d; %d", entry.event, dwErr);
392
400
 
393
401
  /* cond is guarded by mutex */
394
402
  if (cond->next) {
@@ -0,0 +1,6 @@
1
+ package com.rho;
2
+
3
+ public class Capabilities {
4
+ public static final boolean ENABLE_PUSH = true;
5
+ public static final boolean RUNAS_SERVICE = true;
6
+ }
@@ -158,7 +158,7 @@ public class RhodesApp
158
158
  String strBody = "rho_callback=1";
159
159
 
160
160
  strBody += "&width="; strBody += width;
161
- strBody += "&heigth="; strBody += height;
161
+ strBody += "&height="; strBody += height;
162
162
  strBody += "&degrees="; strBody += degrees;
163
163
 
164
164
  if ( m_strScreenRotationCallbackParams.length() > 0 )
@@ -64,7 +64,7 @@ public class ClientRegister extends RhoThread
64
64
  public void run()
65
65
  {
66
66
  LOG.INFO("ClientRegister start");
67
- while(true)
67
+ while(!m_bStop)
68
68
  {
69
69
  try
70
70
  {
@@ -1,6 +1,6 @@
1
1
  package com.xruby.GeneratedMethods;
2
+ import com.xruby.runtime.builtin.RubyString;
2
3
  import com.xruby.runtime.lang.*;
3
- import com.xruby.runtime.lang.RubySymbol;
4
4
  public class RubySymbol_Methods{
5
5
  public static void initMethods( RubyClass klass){
6
6
 
@@ -24,6 +24,11 @@ klass.defineMethod( "to_s", new RubyNoArgMethod(){
24
24
  klass.aliasMethod("id2name","to_s");
25
25
  klass.aliasMethod("to_str","to_s");
26
26
 
27
+ klass.defineMethod( "length", new RubyNoArgMethod(){
28
+ protected RubyValue run(RubyValue receiver, RubyBlock block ){
29
+ return ((RubySymbol)receiver).rubyLength();}
30
+ });
31
+
27
32
  klass.defineMethod( "===", new RubyOneArgMethod(){
28
33
  protected RubyValue run(RubyValue receiver, RubyValue arg, RubyBlock block ){
29
34
  return ((RubySymbol)receiver).sym_eqq(arg);}
@@ -123,9 +123,9 @@ klass.defineMethod( "zone", new RubyNoArgMethod(){
123
123
  return ((RubyTime)receiver).zone();}
124
124
  });
125
125
 
126
- klass.defineMethod( "initialize", new RubyNoArgMethod(){
127
- protected RubyValue run(RubyValue receiver, RubyBlock block ){
128
- return ((RubyTime)receiver).initialize();}
126
+ klass.defineMethod( "initialize", new RubyVarArgMethod(){
127
+ protected RubyValue run(RubyValue receiver, RubyArray args, RubyBlock block ){
128
+ return ((RubyTime)receiver).initialize(args);}
129
129
  });
130
130
  klass.defineAllocMethod(new RubyNoArgMethod(){
131
131
  protected RubyValue run(RubyValue receiver, RubyBlock block ) {
@@ -20,7 +20,7 @@ public class InputStreamExecutor implements RubyIOExecutor {
20
20
  m_is = is;
21
21
  }
22
22
  public InputStreamExecutor(String filename, String mode) {
23
- if ( mode != "r" )
23
+ if ( !mode.equals("r") )
24
24
  throw new Error("Read Only!");
25
25
 
26
26
  try {
@@ -756,7 +756,11 @@ public class RubyArray extends RubyBasic implements Iterable/*<RubyValue>*/ {
756
756
  }
757
757
 
758
758
  //@RubyLevelMethod(name="each")
759
- public RubyValue each(RubyBlock block) {
759
+ public RubyValue each(RubyBlock block)
760
+ {
761
+ if ( block == null )
762
+ return this;
763
+
760
764
  // for (RubyValue item : array_) {
761
765
  for (Iterator iter = array_.iterator(); iter.hasNext();) {
762
766
  RubyValue item = (RubyValue)iter.next();
@@ -769,7 +773,11 @@ public class RubyArray extends RubyBasic implements Iterable/*<RubyValue>*/ {
769
773
  }
770
774
 
771
775
  //@RubyLevelMethod(name="each_index")
772
- public RubyValue each_index(RubyBlock block) {
776
+ public RubyValue each_index(RubyBlock block)
777
+ {
778
+ if ( block == null )
779
+ return this;
780
+
773
781
  for (int i=0;i<size();i++) {
774
782
  RubyValue v = block.invoke(this, new RubyFixnum(i));
775
783
  if (block.breakedOrReturned()) {
@@ -780,7 +788,11 @@ public class RubyArray extends RubyBasic implements Iterable/*<RubyValue>*/ {
780
788
  }
781
789
 
782
790
  //@RubyLevelMethod(name="reverse_each")
783
- public RubyValue reverse_each(RubyBlock block) {
791
+ public RubyValue reverse_each(RubyBlock block)
792
+ {
793
+ if ( block == null )
794
+ return this;
795
+
784
796
  ListIterator/*<RubyValue>*/ ite = array_.listIterator(array_.size());
785
797
  while (ite.hasPrevious()) {
786
798
  RubyValue v = block.invoke(this, (RubyValue)ite.previous());
@@ -128,7 +128,10 @@ public class RubyString extends RubyBasic {
128
128
  return appendString((RubyString)v);
129
129
  } else {
130
130
  RubyValue r = RubyAPI.callPublicNoArgMethod(v, null, RubyID.toSID);
131
- return appendString((RubyString)r);
131
+ if ( r instanceof RubyString )
132
+ return appendString((RubyString)r);
133
+
134
+ return ObjectFactory.createString(r.toString());
132
135
  }
133
136
  }
134
137
 
@@ -907,7 +910,9 @@ public class RubyString extends RubyBasic {
907
910
  //@RubyLevelMethod(name="each", alias="each_line")
908
911
  public RubyValue each(RubyBlock block) {
909
912
  // FIXME: for each line
910
- block.invoke(this, this);
913
+ if ( block != null )
914
+ block.invoke(this, this);
915
+
911
916
  return this;
912
917
  }
913
918
 
@@ -1277,6 +1282,9 @@ public class RubyString extends RubyBasic {
1277
1282
  //@RubyLevelMethod(name="each_byte")
1278
1283
  public RubyValue each_byte(RubyBlock block)
1279
1284
  {
1285
+ if ( block == null )
1286
+ return this;
1287
+
1280
1288
  String string = toString();
1281
1289
  byte bytes[] = null;
1282
1290
  try{
@@ -49,7 +49,18 @@ public class RubyTime extends RubyBasic {
49
49
 
50
50
  //RHO_COMMENT : initialize
51
51
  //@RubyLevelMethod(name="initialize")
52
- public RubyTime initialize() {
52
+ public RubyTime initialize(RubyArray args)
53
+ {
54
+ if ( args != null )
55
+ {
56
+ if ( args.size() > 0 )
57
+ date_.set(Calendar.YEAR, args.get(0).toInt());
58
+ if ( args.size() > 1 )
59
+ date_.set(Calendar.MONTH, args.get(1).toInt()-1);
60
+ if ( args.size() > 2 )
61
+ date_.set(Calendar.DAY_OF_MONTH, args.get(2).toInt());
62
+ }
63
+
53
64
  return this;
54
65
  }
55
66
 
@@ -763,24 +763,33 @@ public class RubyKernelModule {
763
763
  //@RubyLevelMethod(name="open")
764
764
  public static RubyValue open(RubyValue receiver, RubyArray args, RubyBlock block) {
765
765
  String filename = args.get(0).toStr();
766
- RubyIO io;
766
+ String mode = "r";
767
+
768
+ //RHO_COMMENT
769
+ RubyIO io = null;
767
770
  if (args.size() <= 1) {
768
- //io = ObjectFactory.createFile(filename, "r");
769
- //RHO_COMMENT
770
- io = ObjectFactory.createResourceFile(filename, "r");
771
- //RHO_COMMENT
772
771
  } else if (args.get(1) instanceof RubyFixnum) {
773
- String mode = "r";
774
772
  int i = args.get(1).toInt();
775
773
  if ((i & RDWR) != 0) {
776
774
  mode = mode + "w";
777
775
  }
778
- io = ObjectFactory.createFile(filename, mode);
779
776
  } else {
780
- RubyString mode = (RubyString) args.get(1);
781
- io = ObjectFactory.createFile(filename, mode.toString());
777
+ RubyString val = (RubyString) args.get(1);
778
+ mode = val.toString();
782
779
  }
783
780
 
781
+ try{
782
+ io = ObjectFactory.createResourceFile(filename, mode);
783
+ }catch (java.lang.Error exc)
784
+ {
785
+ LOG.ERROR("Cannot open file from jar: " + filename, exc);
786
+ }
787
+
788
+ if ( io == null )
789
+ io = ObjectFactory.createFile(filename, mode);
790
+
791
+ //RHO_COMMENT
792
+
784
793
  if (null == block) {
785
794
  return io;
786
795
  } else {
@@ -72,6 +72,11 @@ public class RubySymbol extends RubyValue {
72
72
  return this;
73
73
  }
74
74
 
75
+ //@RubyLevelMethod(name="length")
76
+ public RubyFixnum rubyLength() {
77
+ return ObjectFactory.createFixnum(id.toString().length());
78
+ }
79
+
75
80
  //@RubyLevelMethod(name="inspect")
76
81
  public RubyString rubyInspect() {
77
82
  String value = this.toString();
@@ -214,7 +214,8 @@ public class JSONArray {
214
214
  public double getDouble(int index) throws JSONException {
215
215
  Object o = get(index);
216
216
  try {
217
- return Double.valueOf((String)o).doubleValue();
217
+ Double v = (o instanceof Double) ? (Double)o : Double.valueOf((String)o);
218
+ return v.doubleValue();
218
219
  } catch (Exception e) {
219
220
  throw new JSONException("JSONArray[" + index +
220
221
  "] is not a number.");
@@ -1696,7 +1696,7 @@ int inflate_blocks_free(inflate_blocks_statef *s, z_streamp z)
1696
1696
 
1697
1697
 
1698
1698
 
1699
- extern const char inflate_copyright[] =
1699
+ extern const char zlib_inflate_copyright[] =
1700
1700
  " inflate 1.1.3 Copyright 1995-1998 Mark Adler ";
1701
1701
  // If you use the zlib library in a product, an acknowledgment is welcome
1702
1702
  // in the documentation of your product. If for some reason you cannot
@@ -204,27 +204,48 @@ namespace "run" do
204
204
  task :dev => ["device:wm:production"] do
205
205
  cd $startdir + "/res/build-tools"
206
206
  detool = "detool.exe"
207
- args = ['dev', $targetdir + '/' + $appname + ".cab", $appname]
207
+ args = [ 'dev', $appname, $srcdir, $startdir + "/" + $vcbindir + "/#{$sdk}" + "/rhodes/Release/rhodes.exe" ]
208
208
  puts "\nStarting application on the device"
209
209
  puts "Please, connect you device via ActiveSync.\n\n"
210
- puts Jake.run(detool,args)
210
+ Jake.run(detool,args)
211
211
  end
212
212
 
213
213
  desc "Build and run on WM6 emulator"
214
214
  task :emu => ["device:wm:production"] do
215
+ cd $startdir + "/res/build-tools"
216
+ detool = "detool.exe"
217
+ args = [ 'emu', '"Windows Mobile 6 Professional Emulator"', $appname, $srcdir, $startdir + "/" + $vcbindir + "/#{$sdk}" + "/rhodes/Release/rhodes.exe" ]
218
+ puts "\nStarting application on the WM6 emulator\n\n"
219
+ Jake.run(detool,args)
220
+ end
221
+
222
+ desc "Build, install .cab and run on the Windows Phone"
223
+ task :devcab => ["device:wm:production"] do
224
+ cd $startdir + "/res/build-tools"
225
+ detool = "detool.exe"
226
+ args = ['devcab', $targetdir + '/' + $appname + ".cab", $appname]
227
+ puts "\nStarting application on the device"
228
+ puts "Please, connect you device via ActiveSync.\n\n"
229
+ Jake.run(detool,args)
230
+ end
231
+
232
+ desc "Build, install .cab and run on WM6 emulator"
233
+ task :emucab => ["device:wm:production"] do
215
234
  cd $startdir + "/res/build-tools"
216
235
  detool = "detool.exe"
217
- args = ['emu', '"Windows Mobile 6 Professional Emulator"', $targetdir + '/' + $appname + ".cab", $appname]
236
+ args = ['emucab', '"Windows Mobile 6 Professional Emulator"', $targetdir + '/' + $appname + ".cab", $appname]
218
237
  puts "\nStarting application on the WM6 emulator\n\n"
219
- puts Jake.run(detool,args)
238
+ Jake.run(detool,args)
220
239
  end
221
240
  end
222
241
 
223
242
  desc "Run win32"
224
243
  task :win32 => ["build:win32"] do
225
244
  args = [' ']
226
- chdir $config["build"]["wmpath"]
227
- Thread.new { Jake.run("bin\\win32\\rhodes\\Debug\\rhodes", args) }
245
+ # chdir $config["build"]["wmpath"]
246
+ # Thread.new { Jake.run("bin\\win32\\rhodes\\Debug\\rhodes", args) }
247
+ Jake.run2 "bin\\win32\\rhodes\\Debug\\rhodes.exe", args, {:directory => $config["build"]["wmpath"], :nowait => true}
248
+
228
249
  $stdout.flush
229
250
  chdir $startdir
230
251
 
@@ -5,6 +5,7 @@
5
5
  #endif
6
6
 
7
7
  #include <common/RhodesApp.h>
8
+ #include <common/rhoparams.h>
8
9
 
9
10
  #include "Alert.h"
10
11
  #include "MainWindow.h"
@@ -12,13 +13,259 @@
12
13
 
13
14
  extern "C" HWND getMainWnd();
14
15
 
16
+ /**
17
+ ********************************************************************************
18
+ * CAlertDialog members.
19
+ ********************************************************************************
20
+ */
21
+
22
+ //TODO:
23
+ // - smart alignment and win32
24
+ // - review for memory leaks.
25
+
26
+ typedef CWinTraits <WS_CAPTION | WS_VISIBLE | WS_POPUP | DS_CENTER> CAlertDialogTraits;
27
+
28
+ CAlertDialog::CAlertDialog(Params *params)
29
+ {
30
+ m_title = params->m_title;
31
+ m_message = params->m_message;
32
+ m_callback = params->m_callback;
33
+ m_icon = params->m_icon;
34
+
35
+ int id = ID_ALERT_DLG_BUTTON_FIRST;
36
+ for (Hashtable<String, String>::iterator itr = params->m_buttons.begin(); itr != params->m_buttons.end(); ++itr) {
37
+ if(id > ID_ALERT_DLG_BUTTON_LAST) {
38
+ LOG(ERROR) + "too many buttons";
39
+ break;
40
+ }
41
+ m_buttons.addElement(CustomButton(itr->first, itr->second, id++));
42
+ }
43
+ }
44
+
45
+ CAlertDialog::~CAlertDialog()
46
+ {
47
+ }
48
+
49
+ void CAlertDialog::DoInitTemplate()
50
+ {
51
+ #ifdef OS_WINCE
52
+ int initialWidth = GetSystemMetrics(SM_CXSCREEN)/3;
53
+ #else
54
+ int initialWidth = CMainWindow::getScreenWidth()/3;
55
+ #endif
56
+ int initialHeight = initialWidth/3;
57
+
58
+ m_Template.Create(false, convertToStringW(m_title).c_str(),
59
+ 0,
60
+ 0,
61
+ initialWidth,
62
+ initialHeight,
63
+ CAlertDialogTraits::GetWndStyle(0),
64
+ CAlertDialogTraits::GetWndExStyle(0));
65
+ }
66
+
67
+ void CAlertDialog::DoInitControls()
68
+ {
69
+ }
70
+
71
+ LRESULT CAlertDialog::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL&bHandled)
72
+ {
73
+ #define MAX(i, j) ((i) > (j) ? (i) : (j))
74
+
75
+ const int GAP = 10; //space around dialog
76
+ const int INDENT = 8; //for dialog items
77
+ const unsigned int iconHeight = 42;
78
+ //space around label on buttons.
79
+ const int btnHIndent = 12; //horizontal
80
+ const int btnVIndent = 8; //vertical
81
+ #ifdef OS_WINCE
82
+ unsigned int maxWidth = GetSystemMetrics(SM_CXSCREEN) - (GAP * 2);
83
+ unsigned int maxHeight = GetSystemMetrics(SM_CYSCREEN) - (GAP * 2);
84
+ #else
85
+ unsigned int maxWidth = CMainWindow::getScreenWidth() - (GAP * 2);
86
+ unsigned int maxHeight = CMainWindow::getScreenWidth() - (GAP * 2);
87
+ #endif
88
+ unsigned int msgWidth = 0, msgHeight = 0;
89
+ CClientDC dc(m_hWnd);
90
+ TEXTMETRIC tm = { 0 };
91
+ RECT dlgRect, iconRect = {0 }, msgRect = { 0 }, buttonsRect = { 0 };
92
+ RECT rect = {0}; POINT point = { 0 };
93
+ #ifdef OS_WINCE
94
+ int iconId = 0;
95
+ #else
96
+ LPWSTR iconId = NULL;
97
+ #endif
98
+
99
+ GetClientRect(&dlgRect);
100
+ LOG(INFO) + "dlgRect: " + dlgRect.left + " " + dlgRect.top + " " + dlgRect.right + " " + dlgRect.bottom;
101
+
102
+ /**
103
+ * Icon.
104
+ */
105
+ #ifdef OS_WINCE
106
+ if (m_icon == "alert")
107
+ iconId = MB_ICONWARNING;
108
+ else if (m_icon == "question")
109
+ iconId = MB_ICONQUESTION;
110
+ else if (m_icon == "info")
111
+ iconId = MB_ICONINFORMATION;
112
+ #else
113
+ if (m_icon == "alert")
114
+ iconId = IDI_WARNING;
115
+ else if (m_icon == "question")
116
+ iconId = IDI_QUESTION;
117
+ else if (m_icon == "info")
118
+ iconId = IDI_INFORMATION;
119
+ #endif
120
+
121
+ //if icon has predefined type - try to load it from system resources.
122
+ if (iconId != 0) {
123
+ #ifdef OS_WINCE
124
+ HMODULE hGWES = LoadLibraryEx( L"gwes.exe", NULL, LOAD_LIBRARY_AS_DATAFILE );
125
+ HICON hIcon = LoadIcon(hGWES, MAKEINTRESOURCE(iconId));
126
+ #else
127
+ HICON hIcon = LoadIcon(NULL, iconId);
128
+ #endif
129
+
130
+ if (hIcon == NULL) {
131
+ LOG(ERROR) + "Failed to load icon";
132
+ } else {
133
+ iconRect.left = INDENT;
134
+ iconRect.top = INDENT;
135
+ iconRect.right = iconRect.left + iconHeight;
136
+ iconRect.bottom = iconRect.top + iconHeight;
137
+
138
+ m_iconCtrl.Create(m_hWnd, iconRect, NULL, WS_CHILD | WS_VISIBLE | SS_ICON);
139
+
140
+ if (m_iconCtrl.SetIcon(hIcon) == NULL)
141
+ LOG(INFO) + "Failed to set icon";
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Message.
147
+ */
148
+ GetClientRect(&dlgRect);
149
+ dc.GetTextMetrics(&tm);
150
+
151
+ msgWidth = m_message.length() * tm.tmAveCharWidth + (2 * INDENT);
152
+ msgHeight = (tm.tmHeight + tm.tmExternalLeading + tm.tmInternalLeading);
153
+ point.x = iconRect.right; point.y = iconRect.top;
154
+
155
+ int desiredDlgWidth = iconRect.right + msgWidth + (INDENT * 2);
156
+
157
+ //if ((desiredDlgWidth > (dlgRect.right - dlgRect.left))) { //adjust dialog window
158
+ if ( m_buttons.size() != 0 ) {
159
+ if ((point.x + msgWidth) > maxWidth) {
160
+ msgWidth = maxWidth - iconRect.right;
161
+ msgHeight = (((m_message.length() * tm.tmAveCharWidth) / msgWidth) + 1)
162
+ * (tm.tmHeight + tm.tmExternalLeading + tm.tmInternalLeading);
163
+ desiredDlgWidth = iconRect.right + msgWidth + (INDENT * 2);
164
+ } else {
165
+ msgHeight = tm.tmHeight + tm.tmExternalLeading + tm.tmInternalLeading;
166
+ }
167
+
168
+ if (m_buttons.size() == 0) {
169
+ MoveWindow(GAP, GAP,
170
+ desiredDlgWidth + 13 + INDENT,
171
+ MAX((unsigned int )iconRect.bottom, msgHeight) + msgHeight + GetSystemMetrics(SM_CYCAPTION) + INDENT);
172
+ } else {
173
+ MoveWindow(GAP, GAP,
174
+ desiredDlgWidth + 13 + INDENT,
175
+ MAX((unsigned int )iconRect.bottom, msgHeight) + GetSystemMetrics(SM_CYCAPTION) + INDENT +
176
+ (tm.tmHeight + btnVIndent + INDENT * 2)); //reserved place for buttons
177
+ }
178
+ }
179
+
180
+ msgRect.left = iconRect.right + INDENT;
181
+ msgRect.top = iconRect.top;
182
+ msgRect.right = iconRect.right + msgWidth + 2 * INDENT + INDENT * 2;
183
+ msgRect.bottom = msgRect.top + msgHeight;
184
+
185
+ //LOG(DEBUG) + " msgWidth: " + msgWidth;
186
+ //LOG(DEBUG) + " msgRect: " + msgRect.left + " " + msgRect.top + " " + msgRect.right + " " + msgRect.bottom;
187
+
188
+ m_messageCtrl.Create(m_hWnd, msgRect, NULL, WS_CHILD | WS_VISIBLE);
189
+ m_messageCtrl.SetWindowText(convertToStringW(m_message).c_str());
190
+
191
+ //for Wait dailog text should be centered
192
+ if (m_buttons.size() == 0) {
193
+ m_messageCtrl.CenterWindow();
194
+ }
195
+
196
+ /**
197
+ * Buttons.
198
+ */
199
+ int btnsNum = m_buttons.size();
200
+ int btnsWidth = 0, btnsHeight =tm.tmHeight + btnVIndent;
201
+
202
+ for (Vector<CustomButton>::iterator itr = m_buttons.begin(); itr != m_buttons.end(); ++itr) {
203
+ btnsWidth += (itr->m_title.length() * tm.tmAveCharWidth) + btnHIndent + (INDENT * 2);
204
+ }
205
+
206
+ point.x = INDENT, point.y = (iconHeight > msgHeight ? point.y = iconHeight + 6 : msgHeight + 2) + INDENT;
207
+
208
+ unsigned int btnWidth = 0, btnHeight = 0;
209
+ for (Vector<CustomButton>::iterator itr = m_buttons.begin(); itr != m_buttons.end(); ++itr) {
210
+ btnWidth = (itr->m_title.length() * tm.tmAveCharWidth) + btnHIndent;
211
+ btnHeight = tm.tmHeight + btnVIndent;
212
+
213
+ RECT rc = {point.x, point.y, point.x + btnWidth, point.y + btnHeight};
214
+ itr->Create(m_hWnd, rc,
215
+ convertToStringW(itr->m_title).c_str(),
216
+ WS_CHILD | WS_VISIBLE
217
+ #if defined(OS_WINDOWS)
218
+ | BS_DEFPUSHBUTTON
219
+ #endif
220
+ , 0,
221
+ itr->m_numId);
222
+
223
+ point.x += btnWidth + INDENT;
224
+ }
225
+
226
+ CenterWindow();
227
+
228
+ return bHandled = FALSE;
229
+
230
+ #undef MAX
231
+ }
232
+
233
+ bool CAlertDialog::findButton(int id, CustomButton &btn)
234
+ {
235
+ for (Vector<CustomButton>::iterator itr = m_buttons.begin(); itr != m_buttons.end(); ++itr) {
236
+ if (itr->m_numId == id) {
237
+ btn = *itr;
238
+ return true;
239
+ }
240
+ }
241
+
242
+ return false;
243
+ }
244
+
245
+ LRESULT CAlertDialog::OnAlertDialogButton (WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
246
+ {
247
+ CustomButton cbtn;
248
+ if (findButton((int) wID, cbtn))
249
+ rho_rhodesapp_callPopupCallback(m_callback.c_str(), cbtn.m_strId.c_str(), cbtn.m_title.c_str());
250
+ else
251
+ LOG(ERROR) + "internal error";
252
+
253
+ EndDialog(wID);
254
+ return 0;
255
+ }
256
+
257
+ /**
258
+ ********************************************************************************
259
+ * CAlert members.
260
+ ********************************************************************************
261
+ */
262
+
15
263
  IMPLEMENT_LOGCLASS(CAlert, "Alert");
16
264
 
17
- void CAlert::showPopup(String message)
265
+ void CAlert::showPopup(CAlertDialog::Params *params)
18
266
  {
19
267
  HWND main_wnd = getMainWnd();
20
- ::PostMessage(main_wnd, WM_ALERT_SHOWPOPUP, 0,
21
- (LPARAM )strdup(message.c_str()));
268
+ ::PostMessage(main_wnd, WM_ALERT_SHOW_POPUP, 0, (LPARAM ) params);
22
269
  }
23
270
 
24
271
  #if defined(_WIN32_WCE)
@@ -55,8 +302,89 @@ void CAlert::playFile(String fileName)
55
302
 
56
303
  #endif //_WIN32_WCE
57
304
 
58
- extern "C" void alert_show_popup(char* message) {
59
- CAlert::showPopup(message);
305
+ extern "C" void alert_show_popup(rho_param *p)
306
+ {
307
+ if (p->type == RHO_PARAM_STRING) {
308
+ CAlert::showPopup(new CAlertDialog::Params(String(p->v.string)));
309
+ } else if (p->type == RHO_PARAM_HASH) {
310
+ String title, message, callback, icon;
311
+ String btnId, btnTitle;
312
+ Hashtable<String, String> buttons;
313
+
314
+ for (int i = 0, lim = p->v.hash->size; i < lim; ++i) {
315
+ char *name = p->v.hash->name[i];
316
+ rho_param *value = p->v.hash->value[i];
317
+
318
+ if (strcasecmp(name, "title") == 0) {
319
+ if (value->type != RHO_PARAM_STRING) {
320
+ RAWLOG_ERROR("'title' should be string");
321
+ continue;
322
+ }
323
+ title = value->v.string;
324
+ }
325
+ else if (strcasecmp(name, "message") == 0) {
326
+ if (value->type != RHO_PARAM_STRING) {
327
+ RAWLOG_ERROR("'message' should be string");
328
+ continue;
329
+ }
330
+ message = value->v.string;
331
+ }
332
+ else if (strcasecmp(name, "callback") == 0) {
333
+ if (value->type != RHO_PARAM_STRING) {
334
+ RAWLOG_ERROR("'callback' should be string");
335
+ continue;
336
+ }
337
+ callback = value->v.string;
338
+ } else if (strcasecmp(name, "icon") == 0) {
339
+ if (value->type != RHO_PARAM_STRING) {
340
+ RAWLOG_ERROR("'title' should be string");
341
+ continue;
342
+ }
343
+ icon = value->v.string;
344
+ }
345
+
346
+ else if (strcasecmp(name, "buttons") == 0) {
347
+ if (value->type != RHO_PARAM_ARRAY) {
348
+ RAWLOG_ERROR("'buttons' should be array");
349
+ continue;
350
+ }
351
+ for (int j = 0, limj = value->v.array->size; j < limj; ++j) {
352
+ rho_param *arrValue = value->v.array->value[j];
353
+ switch (arrValue->type) {
354
+ case RHO_PARAM_STRING:
355
+ btnId = arrValue->v.string;
356
+ btnTitle = arrValue->v.string;
357
+ break;
358
+ case RHO_PARAM_HASH:
359
+ for (int k = 0, limk = arrValue->v.hash->size; k < limk; ++k) {
360
+ char *sName = arrValue->v.hash->name[k];
361
+ rho_param *sValue = arrValue->v.hash->value[k];
362
+ if (sValue->type != RHO_PARAM_STRING) {
363
+ RAWLOG_ERROR("Illegal type of button item's value");
364
+ continue;
365
+ }
366
+ if (strcasecmp(sName, "id") == 0)
367
+ btnId = sValue->v.string;
368
+ else if (strcasecmp(sName, "title") == 0)
369
+ btnTitle = sValue->v.string;
370
+ }
371
+ break;
372
+ default:
373
+ RAWLOG_ERROR("Illegal type of button item");
374
+ continue;
375
+ }
376
+ if (btnId == "" || btnTitle == "") {
377
+ RAWLOG_ERROR("Incomplete button item");
378
+ continue;
379
+ }
380
+
381
+ buttons.put(btnTitle, btnId);
382
+ }
383
+ }//buttons
384
+ }
385
+
386
+ CAlert::showPopup(new CAlertDialog::Params(title, message, icon, callback, buttons));
387
+ }
60
388
  }
61
389
 
62
390
  extern "C" void alert_vibrate(void*) {
@@ -73,4 +401,6 @@ extern "C" void alert_play_file(char* file_name, ...) {
73
401
 
74
402
  extern "C" void alert_hide_popup()
75
403
  {
404
+ HWND main_wnd = getMainWnd();
405
+ ::PostMessage(main_wnd, WM_ALERT_HIDE_POPUP, 0, 0);
76
406
  }