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.
- data/CHANGELOG +5 -0
- data/LICENSE +19 -674
- data/Manifest.txt +21 -4
- data/README.textile +5 -36
- data/Rakefile +5 -0
- data/lib/build/jake.rb +3 -1
- data/lib/extensions/rexml/rexml/document.rb +2 -0
- data/lib/extensions/rexml/rexml/parsers/baseparser.rb +0 -6
- data/lib/extensions/rhoxml/rexml/child.rb +96 -0
- data/lib/extensions/rhoxml/rexml/document.rb +527 -0
- data/lib/extensions/rhoxml/rexml/element.rb +987 -0
- data/lib/extensions/rhoxml/rexml/encoding.rb +71 -0
- data/lib/extensions/rhoxml/rexml/encodings/US-ASCII.rb +30 -0
- data/lib/extensions/rhoxml/rexml/encodings/UTF-16.rb +35 -0
- data/lib/extensions/rhoxml/rexml/encodings/UTF-8.rb +18 -0
- data/lib/extensions/rhoxml/rexml/namespace.rb +47 -0
- data/lib/extensions/rhoxml/rexml/node.rb +76 -0
- data/lib/extensions/rhoxml/rexml/parent.rb +166 -0
- data/lib/extensions/rhoxml/rexml/parseexception.rb +51 -0
- data/lib/extensions/rhoxml/rexml/parsers/baseparser.rb +531 -0
- data/lib/extensions/rhoxml/rexml/parsers/treeparser.rb +100 -0
- data/lib/extensions/rhoxml/rexml/parsers/xpathparser.rb +698 -0
- data/lib/extensions/rhoxml/rexml/set.rb +1274 -0
- data/lib/extensions/rhoxml/rexml/source.rb +258 -0
- data/lib/extensions/rhoxml/rexml/xmltokens.rb +18 -0
- data/lib/extensions/rhoxml/rexml/xpath.rb +77 -0
- data/lib/extensions/rhoxml/rexml/xpath_parser.rb +806 -0
- data/lib/framework/builtinME.rb +2 -0
- data/lib/framework/dateME.rb +5 -1
- data/lib/framework/rho/render.rb +10 -2
- data/lib/framework/rhom/rhom_object_factory.rb +2 -1
- data/lib/framework/singleton.rb +1 -1
- data/platform/android/Rhodes/jni/src/rhodes.cpp +2 -4
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/NativeBar.java +23 -18
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/Rhodes.java +42 -69
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/SplashScreen.java +59 -7
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/camera/Camera.java +1 -1
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/mapview/Annotation.java +1 -0
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/mapview/MapView.java +97 -85
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/uri/SmsUriHandler.java +52 -0
- data/platform/android/build/RhodesSRC_build.files +1 -0
- data/platform/android/build/android.rake +38 -14
- data/platform/bb/RubyVM/RubyVM.jdp +1 -0
- data/platform/bb/build/RubyVM_build.files +1 -0
- data/platform/bb/build/bb.rake +44 -2
- data/platform/bb/rhodes/platform/5.0/com/rho/BrowserAdapter5.java +1 -1
- data/platform/bb/rhodes/rhodes.jdp +4 -4
- data/platform/bb/rhodes/src/com/rho/BrowserAdapter.java +8 -4
- data/platform/bb/rhodes/src/com/rho/rubyext/Alert.java +149 -17
- data/platform/bb/rhodes/src/rhomobile/PushListeningThread.java +20 -17
- data/platform/bb/rhodes/src/rhomobile/RhodesApplication.java +54 -28
- data/platform/bb/rhodes/src/rhomobile/mapview/Annotation.java +1 -0
- data/platform/bb/rhodes/src/rhomobile/mapview/GoogleMapField.java +37 -11
- data/platform/bb/rhodes/src/rhomobile/mapview/MapView.java +49 -19
- data/platform/bb/rhodes/src/rhomobile/mapview/MapViewScreen.java +6 -0
- data/platform/iphone/Classes/MapView/GoogleGeocoder.h +6 -7
- data/platform/iphone/Classes/MapView/GoogleGeocoder.m +70 -70
- data/platform/iphone/Classes/MapView/MapAnnotation.h +5 -3
- data/platform/iphone/Classes/MapView/MapAnnotation.m +10 -8
- data/platform/iphone/Classes/MapView/MapViewController.h +13 -10
- data/platform/iphone/Classes/MapView/MapViewController.m +131 -72
- data/platform/iphone/Classes/Rhodes.h +2 -0
- data/platform/iphone/Classes/Rhodes.m +13 -1
- data/platform/iphone/Classes/SimpleMainView.m +0 -1
- data/platform/iphone/Classes/TabbedMainView.m +5 -6
- data/platform/shared/common/RhoTime.h +2 -2
- data/platform/shared/common/RhodesApp.cpp +1 -1
- data/platform/shared/db/DBAdapter.cpp +6 -0
- data/platform/shared/net/CURLNetRequest.cpp +23 -1
- data/platform/shared/ruby/thread_win32.c +9 -1
- data/platform/shared/rubyJVM/src/com/rho/Capabilities.java +6 -0
- data/platform/shared/rubyJVM/src/com/rho/RhodesApp.java +1 -1
- data/platform/shared/rubyJVM/src/com/rho/sync/ClientRegister.java +1 -1
- data/platform/shared/rubyJVM/src/com/xruby/GeneratedMethods/RubySymbol_Methods.java +6 -1
- data/platform/shared/rubyJVM/src/com/xruby/GeneratedMethods/RubyTime_Methods.java +3 -3
- data/platform/shared/rubyJVM/src/com/xruby/runtime/builtin/InputStreamExecutor.java +1 -1
- data/platform/shared/rubyJVM/src/com/xruby/runtime/builtin/RubyArray.java +15 -3
- data/platform/shared/rubyJVM/src/com/xruby/runtime/builtin/RubyString.java +10 -2
- data/platform/shared/rubyJVM/src/com/xruby/runtime/builtin/RubyTime.java +12 -1
- data/platform/shared/rubyJVM/src/com/xruby/runtime/lang/RubyKernelModule.java +18 -9
- data/platform/shared/rubyJVM/src/com/xruby/runtime/lang/RubySymbol.java +5 -0
- data/platform/shared/rubyJVM/src/org/json/me/JSONArray.java +2 -1
- data/platform/shared/unzip/unzip.cpp +1 -1
- data/platform/wm/build/wm.rake +27 -6
- data/platform/wm/rhodes/Alert.cpp +335 -5
- data/platform/wm/rhodes/Alert.h +84 -1
- data/platform/wm/rhodes/MainWindow.cpp +28 -6
- data/platform/wm/rhodes/MainWindow.h +7 -2
- data/platform/wm/rhodes/Rhodes.cpp +23 -0
- data/platform/wm/rhodes/rho/rubyext/SystemImpl.cpp +2 -1
- data/platform/wm/rhodes/stdafx.h +1 -0
- data/platform/wm/tools/detool/detool.cpp +405 -14
- data/rakefile.rb +5 -0
- data/res/build-tools/detool.exe +0 -0
- data/res/generators/rhogen.rb +2 -0
- data/rhodes.gemspec +1 -1
- data/spec/framework_spec/app/spec/fixtures/object_values.txt +1 -1
- data/spec/framework_spec/app/spec/pagination/fixtures/object_values.txt +1 -1
- data/spec/framework_spec/app/spec/rhom_object_spec.rb +12 -12
- metadata +23 -6
- data/LICENSING_OPTIONS +0 -1
- data/platform/bb/build/rhodesApp.rapc +0 -9
- data/res/generators/templates/source/source_adapter.rb +0 -48
- 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 =
|
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) {
|
@@ -158,7 +158,7 @@ public class RhodesApp
|
|
158
158
|
String strBody = "rho_callback=1";
|
159
159
|
|
160
160
|
strBody += "&width="; strBody += width;
|
161
|
-
strBody += "&
|
161
|
+
strBody += "&height="; strBody += height;
|
162
162
|
strBody += "°rees="; strBody += degrees;
|
163
163
|
|
164
164
|
if ( m_strScreenRotationCallbackParams.length() > 0 )
|
@@ -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
|
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 ) {
|
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
781
|
-
|
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
|
-
|
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
|
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
|
data/platform/wm/build/wm.rake
CHANGED
@@ -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', $
|
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
|
-
|
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 = ['
|
236
|
+
args = ['emucab', '"Windows Mobile 6 Professional Emulator"', $targetdir + '/' + $appname + ".cab", $appname]
|
218
237
|
puts "\nStarting application on the WM6 emulator\n\n"
|
219
|
-
|
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(
|
265
|
+
void CAlert::showPopup(CAlertDialog::Params *params)
|
18
266
|
{
|
19
267
|
HWND main_wnd = getMainWnd();
|
20
|
-
::PostMessage(main_wnd,
|
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(
|
59
|
-
|
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
|
}
|