mirror of https://github.com/buggins/dlangui.git
Android support refactoring; #119
This commit is contained in:
parent
aed940b2f4
commit
2325d3e4df
|
@ -6,6 +6,7 @@ LOCAL_MODULE=dlangui-activity
|
||||||
# applicatino source files
|
# applicatino source files
|
||||||
LOCAL_SRC_FILES="\
|
LOCAL_SRC_FILES="\
|
||||||
jni/main.d \
|
jni/main.d \
|
||||||
|
jni/app.d \
|
||||||
"
|
"
|
||||||
|
|
||||||
# Additional libraries to link
|
# Additional libraries to link
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
module app;
|
||||||
|
|
||||||
|
import dlangui;
|
||||||
|
|
||||||
|
mixin APP_ENTRY_POINT;
|
||||||
|
|
||||||
|
/// entry point for dlangui based application
|
||||||
|
extern (C) int UIAppMain(string[] args) {
|
||||||
|
// create window
|
||||||
|
Log.d("Creating window");
|
||||||
|
if (!Platform.instance) {
|
||||||
|
Log.e("Platform.instance is null!!!");
|
||||||
|
}
|
||||||
|
Window window = Platform.instance.createWindow("DlangUI example - HelloWorld", null);
|
||||||
|
Log.d("Window created");
|
||||||
|
|
||||||
|
// create some widget to show in window
|
||||||
|
//window.mainWidget = (new Button()).text("Hello, world!"d).margins(Rect(20,20,20,20));
|
||||||
|
window.mainWidget = parseML(q{
|
||||||
|
VerticalLayout {
|
||||||
|
margins: 10
|
||||||
|
padding: 10
|
||||||
|
layoutWidth: fill
|
||||||
|
backgroundColor: "#C0E0E070" // semitransparent yellow background
|
||||||
|
// red bold text with size = 150% of base style size and font face Arial
|
||||||
|
TextWidget { text: "Hello World example for DlangUI"; textColor: "red"; fontSize: 150%; fontWeight: 800; fontFace: "Arial" }
|
||||||
|
// arrange controls as form - table with two columns
|
||||||
|
TableLayout {
|
||||||
|
colCount: 2
|
||||||
|
layoutWidth: fill
|
||||||
|
TextWidget { text: "param 1" }
|
||||||
|
EditLine { id: edit1; text: "some text"; layoutWidth: fill }
|
||||||
|
TextWidget { text: "param 2" }
|
||||||
|
EditLine { id: edit2; text: "some text for param2"; layoutWidth: fill }
|
||||||
|
TextWidget { text: "some radio buttons" }
|
||||||
|
// arrange some radio buttons vertically
|
||||||
|
VerticalLayout {
|
||||||
|
layoutWidth: fill
|
||||||
|
RadioButton { id: rb1; text: "Item 1" }
|
||||||
|
RadioButton { id: rb2; text: "Item 2" }
|
||||||
|
RadioButton { id: rb3; text: "Item 3" }
|
||||||
|
}
|
||||||
|
TextWidget { text: "and checkboxes" }
|
||||||
|
// arrange some checkboxes horizontally
|
||||||
|
HorizontalLayout {
|
||||||
|
layoutWidth: fill
|
||||||
|
CheckBox { id: cb1; text: "checkbox 1" }
|
||||||
|
CheckBox { id: cb2; text: "checkbox 2" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HorizontalLayout {
|
||||||
|
Button { id: btnOk; text: "Ok" }
|
||||||
|
Button { id: btnCancel; text: "Cancel" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// you can access loaded items by id - e.g. to assign signal listeners
|
||||||
|
auto edit1 = window.mainWidget.childById!EditLine("edit1");
|
||||||
|
auto edit2 = window.mainWidget.childById!EditLine("edit2");
|
||||||
|
// close window on Cancel button click
|
||||||
|
window.mainWidget.childById!Button("btnCancel").click = delegate(Widget w) {
|
||||||
|
window.close();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
// show message box with content of editors
|
||||||
|
window.mainWidget.childById!Button("btnOk").click = delegate(Widget w) {
|
||||||
|
window.showMessageBox(UIString("Ok button pressed"d),
|
||||||
|
UIString("Editors content\nEdit1: "d ~ edit1.text ~ "\nEdit2: "d ~ edit2.text));
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// show window
|
||||||
|
window.show();
|
||||||
|
|
||||||
|
// run message loop
|
||||||
|
return Platform.instance.enterMessageLoop();
|
||||||
|
}
|
|
@ -92,10 +92,34 @@ class AndroidPlatform : Platform {
|
||||||
|
|
||||||
protected AndroidWindow[] _windows;
|
protected AndroidWindow[] _windows;
|
||||||
protected AndroidWindow _activeWindow;
|
protected AndroidWindow _activeWindow;
|
||||||
|
engine _engine;
|
||||||
|
|
||||||
|
|
||||||
protected android_app* _appstate;
|
protected android_app* _appstate;
|
||||||
this(android_app* state) {
|
this(android_app* state) {
|
||||||
_appstate = state;
|
_appstate = state;
|
||||||
|
memset(&_engine, 0, engine.sizeof);
|
||||||
|
state.userData = &_engine;
|
||||||
|
state.onAppCmd = &engine_handle_cmd;
|
||||||
|
state.onInputEvent = &engine_handle_input;
|
||||||
|
_engine.app = state;
|
||||||
|
|
||||||
|
// Prepare to monitor accelerometer
|
||||||
|
_engine.sensorManager = ASensorManager_getInstance();
|
||||||
|
_engine.accelerometerSensor = ASensorManager_getDefaultSensor(_engine.sensorManager,
|
||||||
|
ASENSOR_TYPE_ACCELEROMETER);
|
||||||
|
_engine.sensorEventQueue = ASensorManager_createEventQueue(_engine.sensorManager,
|
||||||
|
state.looper, LOOPER_ID_USER, null, null);
|
||||||
|
|
||||||
|
if (state.savedState != null) {
|
||||||
|
// We are starting with a previous saved state; restore from it.
|
||||||
|
_engine.state = *cast(saved_state*)state.savedState;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
~this() {
|
||||||
|
engine_term_display(&_engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -138,8 +162,54 @@ class AndroidPlatform : Platform {
|
||||||
* When returned from this method, application is shutting down.
|
* When returned from this method, application is shutting down.
|
||||||
*/
|
*/
|
||||||
override int enterMessageLoop() {
|
override int enterMessageLoop() {
|
||||||
// TODO:
|
while (1) {
|
||||||
return 0;
|
// Read all pending events.
|
||||||
|
int ident;
|
||||||
|
int events;
|
||||||
|
android_poll_source* source;
|
||||||
|
|
||||||
|
// If not animating, we will block forever waiting for events.
|
||||||
|
// If animating, we loop until all events are read, then continue
|
||||||
|
// to draw the next frame of animation.
|
||||||
|
while ((ident=ALooper_pollAll(_engine.animating ? 0 : -1, null, &events,
|
||||||
|
cast(void**)&source)) >= 0) {
|
||||||
|
|
||||||
|
// Process this event.
|
||||||
|
if (source != null) {
|
||||||
|
source.process(_appstate, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a sensor has data, process it now.
|
||||||
|
if (ident == LOOPER_ID_USER) {
|
||||||
|
if (_engine.accelerometerSensor != null) {
|
||||||
|
ASensorEvent event;
|
||||||
|
while (ASensorEventQueue_getEvents(_engine.sensorEventQueue,
|
||||||
|
&event, 1) > 0) {
|
||||||
|
LOGI("accelerometer: x=%f y=%f z=%f",
|
||||||
|
event.acceleration.x, event.acceleration.y,
|
||||||
|
event.acceleration.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we are exiting.
|
||||||
|
if (_appstate.destroyRequested != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_engine.animating) {
|
||||||
|
// Done with events; draw next animation frame.
|
||||||
|
_engine.state.angle += .01f;
|
||||||
|
if (_engine.state.angle > 1) {
|
||||||
|
_engine.state.angle = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drawing is throttled to the screen update rate, so there
|
||||||
|
// is no need to do timing here.
|
||||||
|
engine_draw_frame(&_engine);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected dstring _clipboardText;
|
protected dstring _clipboardText;
|
||||||
|
@ -393,86 +463,24 @@ extern (C) void android_main(android_app* state) {
|
||||||
Platform.setInstance(_platform);
|
Platform.setInstance(_platform);
|
||||||
|
|
||||||
|
|
||||||
engine engine;
|
|
||||||
|
|
||||||
// Make sure glue isn't stripped.
|
// Make sure glue isn't stripped.
|
||||||
app_dummy();
|
app_dummy();
|
||||||
|
|
||||||
memset(&engine, 0, engine.sizeof);
|
int res = 0;
|
||||||
state.userData = &engine;
|
|
||||||
state.onAppCmd = &engine_handle_cmd;
|
|
||||||
state.onInputEvent = &engine_handle_input;
|
|
||||||
engine.app = state;
|
|
||||||
|
|
||||||
// Prepare to monitor accelerometer
|
version (unittest) {
|
||||||
engine.sensorManager = ASensorManager_getInstance();
|
} else {
|
||||||
engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
|
res = UIAppMain([]);
|
||||||
ASENSOR_TYPE_ACCELEROMETER);
|
}
|
||||||
engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager,
|
|
||||||
state.looper, LOOPER_ID_USER, null, null);
|
|
||||||
|
|
||||||
if (state.savedState != null) {
|
|
||||||
// We are starting with a previous saved state; restore from it.
|
|
||||||
engine.state = *cast(saved_state*)state.savedState;
|
|
||||||
}
|
|
||||||
|
|
||||||
// loop waiting for stuff to do.
|
// loop waiting for stuff to do.
|
||||||
|
Log.d("Destroying Android platform");
|
||||||
|
Platform.setInstance(null);
|
||||||
|
|
||||||
while (1) {
|
releaseResourcesOnAppExit();
|
||||||
// Read all pending events.
|
|
||||||
int ident;
|
|
||||||
int events;
|
|
||||||
android_poll_source* source;
|
|
||||||
|
|
||||||
// If not animating, we will block forever waiting for events.
|
Log.d("Exiting main");
|
||||||
// If animating, we loop until all events are read, then continue
|
|
||||||
// to draw the next frame of animation.
|
|
||||||
while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, null, &events,
|
|
||||||
cast(void**)&source)) >= 0) {
|
|
||||||
|
|
||||||
// Process this event.
|
|
||||||
if (source != null) {
|
|
||||||
source.process(state, source);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a sensor has data, process it now.
|
|
||||||
if (ident == LOOPER_ID_USER) {
|
|
||||||
if (engine.accelerometerSensor != null) {
|
|
||||||
ASensorEvent event;
|
|
||||||
while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
|
|
||||||
&event, 1) > 0) {
|
|
||||||
LOGI("accelerometer: x=%f y=%f z=%f",
|
|
||||||
event.acceleration.x, event.acceleration.y,
|
|
||||||
event.acceleration.z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we are exiting.
|
|
||||||
if (state.destroyRequested != 0) {
|
|
||||||
Log.d("Destroying Android platform");
|
|
||||||
Platform.setInstance(null);
|
|
||||||
|
|
||||||
releaseResourcesOnAppExit();
|
|
||||||
|
|
||||||
Log.d("Exiting main");
|
|
||||||
|
|
||||||
engine_term_display(&engine);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (engine.animating) {
|
|
||||||
// Done with events; draw next animation frame.
|
|
||||||
engine.state.angle += .01f;
|
|
||||||
if (engine.state.angle > 1) {
|
|
||||||
engine.state.angle = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Drawing is throttled to the screen update rate, so there
|
|
||||||
// is no need to do timing here.
|
|
||||||
engine_draw_frame(&engine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1440,9 +1440,12 @@ mixin template APP_ENTRY_POINT() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int main(string[] args)
|
version (Android) {
|
||||||
{
|
} else {
|
||||||
return DLANGUImain(args);
|
int main(string[] args)
|
||||||
|
{
|
||||||
|
return DLANGUImain(args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue