mirror of https://github.com/buggins/dlangui.git
Merge branch 'master' of github.com:buggins/dlangui
This commit is contained in:
commit
5d998a9bb9
|
@ -229,6 +229,7 @@ Clone dependency libraries to dlangui/deps directory
|
|||
git clone https://github.com/DerelictOrg/DerelictSDL2.git
|
||||
git clone https://github.com/gecko0307/dlib.git
|
||||
git clone https://github.com/Dav1dde/gl3n.git
|
||||
git clone https://github.com/nomad-software/x11.git
|
||||
|
||||
Open solution file with Mono-D
|
||||
|
||||
|
|
|
@ -139,6 +139,33 @@
|
|||
-Jviews/res
|
||||
-Jviews/res/i18n
|
||||
-Jviews/res/mdpi
|
||||
-Jviews/res/hdpi</ExtraCompilerArguments>
|
||||
<UnittestMode>false</UnittestMode>
|
||||
<OutputName>libdlangui-monod-linux</OutputName>
|
||||
<Target>StaticLibrary</Target>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<DebugLevel>0</DebugLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugX11|x64' ">
|
||||
<OutputPath>bin\DebugX11</OutputPath>
|
||||
<VersionIds>
|
||||
<VersionIds>
|
||||
<String>USE_X11</String>
|
||||
<String>USE_FREETYPE</String>
|
||||
<String>EmbedStandardResources</String>
|
||||
</VersionIds>
|
||||
</VersionIds>
|
||||
<ObjectsDirectory>obj/DebugX11</ObjectsDirectory>
|
||||
<LinkinThirdPartyLibraries>false</LinkinThirdPartyLibraries>
|
||||
<Libs>
|
||||
<Libs>
|
||||
<Lib>X</Lib>
|
||||
</Libs>
|
||||
</Libs>
|
||||
<ExtraCompilerArguments>-Jviews
|
||||
-Jviews/res
|
||||
-Jviews/res/i18n
|
||||
-Jviews/res/mdpi
|
||||
-Jviews/res/hdpi</ExtraCompilerArguments>
|
||||
<UnittestMode>false</UnittestMode>
|
||||
<OutputName>libdlangui-monod-linux</OutputName>
|
||||
|
@ -277,5 +304,37 @@
|
|||
<Compile Include="3rdparty\fontconfig\functions.d" />
|
||||
<Compile Include="3rdparty\fontconfig\package.d" />
|
||||
<Compile Include="3rdparty\fontconfig\types.d" />
|
||||
<Compile Include="deps\x11\source\x11\keysym.d" />
|
||||
<Compile Include="deps\x11\source\x11\keysymdef.d" />
|
||||
<Compile Include="deps\x11\source\x11\X.d" />
|
||||
<Compile Include="deps\x11\source\x11\Xatom.d" />
|
||||
<Compile Include="deps\x11\source\x11\Xlib.d" />
|
||||
<Compile Include="deps\x11\source\x11\XlibConf.d" />
|
||||
<Compile Include="deps\x11\source\x11\Xlibint.d" />
|
||||
<Compile Include="deps\x11\source\x11\Xlib_xcb.d" />
|
||||
<Compile Include="deps\x11\source\x11\Xmd.d" />
|
||||
<Compile Include="deps\x11\source\x11\Xproto.d" />
|
||||
<Compile Include="deps\x11\source\x11\Xprotostr.d" />
|
||||
<Compile Include="deps\x11\source\x11\Xproto_undef.d" />
|
||||
<Compile Include="deps\x11\source\x11\Xregion.d" />
|
||||
<Compile Include="deps\x11\source\x11\Xresource.d" />
|
||||
<Compile Include="deps\x11\source\x11\Xtos.d" />
|
||||
<Compile Include="deps\x11\source\x11\Xutil.d" />
|
||||
<Compile Include="deps\x11\source\x11\extensions\randr.d" />
|
||||
<Compile Include="deps\x11\source\x11\extensions\render.d" />
|
||||
<Compile Include="deps\x11\source\x11\extensions\Xcomposite.d" />
|
||||
<Compile Include="deps\x11\source\x11\extensions\Xfixes.d" />
|
||||
<Compile Include="deps\x11\source\x11\extensions\Xge.d" />
|
||||
<Compile Include="deps\x11\source\x11\extensions\XI.d" />
|
||||
<Compile Include="deps\x11\source\x11\extensions\XI2.d" />
|
||||
<Compile Include="deps\x11\source\x11\extensions\XInput.d" />
|
||||
<Compile Include="deps\x11\source\x11\extensions\XInput2.d" />
|
||||
<Compile Include="deps\x11\source\x11\extensions\Xrandr.d" />
|
||||
<Compile Include="deps\x11\source\x11\extensions\Xrender.d" />
|
||||
<Compile Include="src\dlangui\platforms\x11\x11app.d" />
|
||||
<Compile Include="src\dlangui\platforms\common\startup.d" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="src\dlangui\platforms\x11\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -43,6 +43,15 @@
|
|||
<Target>StaticLibrary</Target>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<DebugLevel>0</DebugLevel>
|
||||
<ExtraCompilerArguments>-Jviews -Jviews/res -Jviews/res/i18n -Jviews/res/mdpi -Jviews/res/hdpi</ExtraCompilerArguments>
|
||||
<VersionIds>
|
||||
<VersionIds>
|
||||
<String>USE_SDL</String>
|
||||
<String>USE_OPENGL</String>
|
||||
<String>USE_FREETYPE</String>
|
||||
<String>EmbedStandardResources</String>
|
||||
</VersionIds>
|
||||
</VersionIds>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Unittest|x64' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -54,6 +63,15 @@
|
|||
<Target>Executable</Target>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<DebugLevel>0</DebugLevel>
|
||||
<ExtraCompilerArguments>-Jviews -Jviews/res -Jviews/res/i18n -Jviews/res/mdpi -Jviews/res/hdpi</ExtraCompilerArguments>
|
||||
<VersionIds>
|
||||
<VersionIds>
|
||||
<String>USE_SDL</String>
|
||||
<String>USE_OPENGL</String>
|
||||
<String>USE_FREETYPE</String>
|
||||
<String>EmbedStandardResources</String>
|
||||
</VersionIds>
|
||||
</VersionIds>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="src\dlangui\core\collections.d" />
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x64</Platform>
|
||||
<ProjectGuid>{1F050D82-5245-4B51-A554-473194EA0DE9}</ProjectGuid>
|
||||
<Compiler>DMD2</Compiler>
|
||||
<PreferOneStepBuild>true</PreferOneStepBuild>
|
||||
|
@ -26,17 +26,6 @@
|
|||
</Includes>
|
||||
</Includes>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<ObjectsDirectory>obj/Debug</ObjectsDirectory>
|
||||
<LinkinThirdPartyLibraries>false</LinkinThirdPartyLibraries>
|
||||
<UnittestMode>false</UnittestMode>
|
||||
<OutputName>derelictcocoatest-monod-osx</OutputName>
|
||||
<Target>Executable</Target>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<DebugLevel>0</DebugLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ObjectsDirectory>obj/Release</ObjectsDirectory>
|
||||
|
@ -58,6 +47,25 @@
|
|||
<Externalconsole>true</Externalconsole>
|
||||
<DebugLevel>0</DebugLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<VersionIds>
|
||||
<VersionIds>
|
||||
<String>USE_SDL</String>
|
||||
<String>USE_OPENGL</String>
|
||||
<String>USE_FREETYPE</String>
|
||||
<String>EmbedStandardResources</String>
|
||||
</VersionIds>
|
||||
</VersionIds>
|
||||
<ObjectsDirectory>obj/Debug</ObjectsDirectory>
|
||||
<LinkinThirdPartyLibraries>false</LinkinThirdPartyLibraries>
|
||||
<UnittestMode>false</UnittestMode>
|
||||
<OutputName>derelictcocoatest-monod-osx</OutputName>
|
||||
<Target>Executable</Target>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<DebugLevel>0</DebugLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="src\" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -1,43 +1,748 @@
|
|||
module cocoatest;
|
||||
version(OSX):
|
||||
|
||||
import derelict.cocoa;
|
||||
|
||||
import dlangui.core.logger;
|
||||
import dlangui.core.types;
|
||||
import dlangui.core.events;
|
||||
import dlangui.graphics.drawbuf;
|
||||
import std.uuid;
|
||||
import core.stdc.stdlib;
|
||||
import std.string;
|
||||
|
||||
void main(string[] args)
|
||||
{
|
||||
Log.setStderrLogger();
|
||||
Log.setLogLevel(LogLevel.Trace);
|
||||
DerelictCocoa.load();
|
||||
|
||||
NSString appName = NSProcessInfo.processInfo().processName();
|
||||
Log.i("appName = %s", appName);
|
||||
//writefln("appName = %s", appName);
|
||||
|
||||
auto pool = new NSAutoreleasePool;
|
||||
|
||||
auto NSApp = NSApplication.sharedApplication;
|
||||
|
||||
NSApp.setActivationPolicy(NSApplicationActivationPolicyRegular);
|
||||
|
||||
NSMenu menubar = NSMenu.alloc;
|
||||
menubar.init_();
|
||||
NSMenuItem appMenuItem = NSMenuItem.alloc();
|
||||
appMenuItem.init_();
|
||||
menubar.addItem(appMenuItem);
|
||||
NSApp.setMainMenu(menubar);
|
||||
|
||||
NSWindow window = NSWindow.alloc();
|
||||
window.initWithContentRect(NSMakeRect(10, 10, 200, 200),
|
||||
NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask, //NSBorderlessWindowMask,
|
||||
NSBackingStoreBuffered, NO);
|
||||
window.makeKeyAndOrderFront();
|
||||
|
||||
NSView parentView;
|
||||
parentView = window.contentView();
|
||||
|
||||
NSApp.activateIgnoringOtherApps(YES);
|
||||
NSApp.run();
|
||||
|
||||
|
||||
static if (true) {
|
||||
auto pool = new NSAutoreleasePool;
|
||||
NSString appName = NSProcessInfo.processInfo().processName();
|
||||
Log.i("appName = %s", appName);
|
||||
|
||||
CocoaWindow window = new CocoaWindow(cast(void*)null, new IWindowListenerLogger(), 300, 300);
|
||||
Log.d("");
|
||||
} else {
|
||||
|
||||
|
||||
NSString appName = NSProcessInfo.processInfo().processName();
|
||||
Log.i("appName = %s", appName);
|
||||
//writefln("appName = %s", appName);
|
||||
|
||||
auto pool = new NSAutoreleasePool;
|
||||
|
||||
auto NSApp = NSApplication.sharedApplication;
|
||||
|
||||
NSApp.setActivationPolicy(NSApplicationActivationPolicyRegular);
|
||||
|
||||
NSMenu menubar = NSMenu.alloc;
|
||||
menubar.init_();
|
||||
NSMenuItem appMenuItem = NSMenuItem.alloc();
|
||||
appMenuItem.init_();
|
||||
menubar.addItem(appMenuItem);
|
||||
NSApp.setMainMenu(menubar);
|
||||
|
||||
NSWindow window = NSWindow.alloc();
|
||||
window.initWithContentRect(NSMakeRect(10, 10, 200, 200),
|
||||
NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask, //NSBorderlessWindowMask,
|
||||
NSBackingStoreBuffered, NO);
|
||||
window.makeKeyAndOrderFront();
|
||||
|
||||
NSView parentView;
|
||||
parentView = window.contentView();
|
||||
|
||||
Log.i("parentView=", parentView);
|
||||
|
||||
NSApp.activateIgnoringOtherApps(YES);
|
||||
|
||||
// string uuid = randomUUID().toString();
|
||||
// DlanguiCocoaView.customClassName = "DlanguiCocoaView_" ~ uuid;
|
||||
// DlanguiCocoaView.registerSubclass();
|
||||
//
|
||||
// _view = DlanguiCocoaView.alloc();
|
||||
// _view.initialize(this, width, height);
|
||||
//
|
||||
// parentView.addSubview(_view);
|
||||
|
||||
|
||||
NSApp.run();
|
||||
}
|
||||
|
||||
DerelictCocoa.unload();
|
||||
}
|
||||
|
||||
interface IWindowListener {
|
||||
void onMouseWheel(int x, int y, int deltaX, int deltaY, MouseState state);
|
||||
void onKeyDown(uint key);
|
||||
void onKeyUp(uint key);
|
||||
void onMouseMove(int x, int y, int deltaX, int deltaY,
|
||||
MouseState mouseState);
|
||||
void onMouseRelease(int x, int y, MouseButton mb, MouseState mouseState);
|
||||
void onMouseClick(int x, int y, MouseButton mb, bool isDoubleClick, MouseState mouseState);
|
||||
void recomputeDirtyAreas();
|
||||
void onResized(int width, int height);
|
||||
void onAnimate(double dt, double time);
|
||||
Rect getDirtyRectangle();
|
||||
}
|
||||
|
||||
class IWindowListenerLogger : IWindowListener {
|
||||
override void onMouseWheel(int x, int y, int deltaX, int deltaY, MouseState state) {
|
||||
Log.d("onMouseWheel");
|
||||
}
|
||||
override void onKeyDown(uint key) {
|
||||
Log.d("onKeyDown");
|
||||
}
|
||||
override void onKeyUp(uint key) {
|
||||
Log.d("onKeyUp");
|
||||
}
|
||||
override void onMouseMove(int x, int y, int deltaX, int deltaY,
|
||||
MouseState mouseState) {
|
||||
Log.d("onMouseMove");
|
||||
}
|
||||
override void onMouseRelease(int x, int y, MouseButton mb, MouseState mouseState) {
|
||||
Log.d("onMouseRelease");
|
||||
}
|
||||
override void onMouseClick(int x, int y, MouseButton mb, bool isDoubleClick, MouseState mouseState) {
|
||||
Log.d("onMouseClick");
|
||||
}
|
||||
override void recomputeDirtyAreas() {
|
||||
//Log.d("recomputeDirtyAreas");
|
||||
}
|
||||
override void onResized(int width, int height) {
|
||||
Log.d("onResized");
|
||||
}
|
||||
override void onAnimate(double dt, double time) {
|
||||
//Log.d("onAnimate");
|
||||
}
|
||||
override Rect getDirtyRectangle() {
|
||||
return Rect(0, 0, 100, 100);
|
||||
}
|
||||
}
|
||||
|
||||
struct MouseState {
|
||||
bool leftButtonDown;
|
||||
bool rightButtonDown;
|
||||
bool middleButtonDown;
|
||||
bool ctrlPressed;
|
||||
bool shiftPressed;
|
||||
bool altPressed;
|
||||
}
|
||||
|
||||
enum MouseButton : int {
|
||||
left,
|
||||
right,
|
||||
middle
|
||||
}
|
||||
|
||||
final class CocoaWindow
|
||||
{
|
||||
private:
|
||||
IWindowListener _listener;
|
||||
|
||||
// Stays null in the case of a plugin, but exists for a stand-alone program
|
||||
// For testing purpose.
|
||||
NSWindow _cocoaWindow = null;
|
||||
NSApplication _cocoaApplication;
|
||||
|
||||
NSColorSpace _nsColorSpace;
|
||||
CGColorSpaceRef _cgColorSpaceRef;
|
||||
NSData _imageData;
|
||||
NSString _logFormatStr;
|
||||
|
||||
ColorDrawBuf _drawBuf;
|
||||
|
||||
DPlugCustomView _view = null;
|
||||
|
||||
bool _terminated = false;
|
||||
|
||||
int _lastMouseX, _lastMouseY;
|
||||
bool _firstMouseMove = true;
|
||||
|
||||
int _width;
|
||||
int _height;
|
||||
|
||||
ubyte* _buffer = null;
|
||||
|
||||
uint _timeAtCreationInMs;
|
||||
uint _lastMeasturedTimeInMs;
|
||||
bool _dirtyAreasAreNotYetComputed;
|
||||
|
||||
public:
|
||||
|
||||
this(void* parentWindow, IWindowListener listener, int width, int height)
|
||||
{
|
||||
_listener = listener;
|
||||
|
||||
DerelictCocoa.load();
|
||||
NSApplicationLoad(); // to use Cocoa in Carbon applications
|
||||
bool parentViewExists = parentWindow !is null;
|
||||
NSView parentView;
|
||||
if (!parentViewExists)
|
||||
{
|
||||
// create a NSWindow to hold our NSView
|
||||
_cocoaApplication = NSApplication.sharedApplication;
|
||||
_cocoaApplication.setActivationPolicy(NSApplicationActivationPolicyRegular);
|
||||
|
||||
NSWindow window = NSWindow.alloc();
|
||||
window.initWithContentRect(NSMakeRect(100, 100, width, height),
|
||||
NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask,
|
||||
NSBackingStoreBuffered,
|
||||
NO);
|
||||
window.makeKeyAndOrderFront();
|
||||
|
||||
parentView = window.contentView();
|
||||
|
||||
_cocoaApplication.activateIgnoringOtherApps(YES);
|
||||
}
|
||||
else
|
||||
parentView = NSView(cast(id)parentWindow);
|
||||
|
||||
|
||||
|
||||
_width = 0;
|
||||
_height = 0;
|
||||
|
||||
_nsColorSpace = NSColorSpace.sRGBColorSpace();
|
||||
// hopefully not null else the colors will be brighter
|
||||
_cgColorSpaceRef = _nsColorSpace.CGColorSpace();
|
||||
|
||||
_logFormatStr = NSString.stringWith("%@");
|
||||
|
||||
_timeAtCreationInMs = getTimeMs();
|
||||
_lastMeasturedTimeInMs = _timeAtCreationInMs;
|
||||
|
||||
_dirtyAreasAreNotYetComputed = true;
|
||||
|
||||
string uuid = randomUUID().toString();
|
||||
DPlugCustomView.customClassName = "DPlugCustomView_" ~ uuid;
|
||||
DPlugCustomView.registerSubclass();
|
||||
|
||||
_view = DPlugCustomView.alloc();
|
||||
_view.initialize(this, width, height);
|
||||
|
||||
parentView.addSubview(_view);
|
||||
|
||||
if (_cocoaApplication)
|
||||
_cocoaApplication.run();
|
||||
|
||||
|
||||
}
|
||||
|
||||
~this()
|
||||
{
|
||||
if (_view)
|
||||
{
|
||||
//debug ensureNotInGC("CocoaWindow");
|
||||
_terminated = true;
|
||||
|
||||
{
|
||||
_view.killTimer();
|
||||
}
|
||||
|
||||
_view.removeFromSuperview();
|
||||
_view.release();
|
||||
_view = DPlugCustomView(null);
|
||||
|
||||
DPlugCustomView.unregisterSubclass();
|
||||
|
||||
if (_buffer != null)
|
||||
{
|
||||
free(_buffer);
|
||||
_buffer = null;
|
||||
}
|
||||
|
||||
DerelictCocoa.unload();
|
||||
}
|
||||
}
|
||||
|
||||
// Implements IWindow
|
||||
void waitEventAndDispatch()
|
||||
{
|
||||
assert(false); // not implemented in Cocoa, since we don't have a NSWindow
|
||||
}
|
||||
|
||||
bool terminated()
|
||||
{
|
||||
return _terminated;
|
||||
}
|
||||
|
||||
void debugOutput(string s)
|
||||
{
|
||||
import core.stdc.stdio;
|
||||
fprintf(stderr, toStringz(s));
|
||||
}
|
||||
|
||||
uint getTimeMs()
|
||||
{
|
||||
return cast(uint)(NSDate.timeIntervalSinceReferenceDate() * 1000.0);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
MouseState getMouseState(NSEvent event)
|
||||
{
|
||||
// not working
|
||||
MouseState state;
|
||||
uint pressedMouseButtons = event.pressedMouseButtons();
|
||||
if (pressedMouseButtons & 1)
|
||||
state.leftButtonDown = true;
|
||||
if (pressedMouseButtons & 2)
|
||||
state.rightButtonDown = true;
|
||||
if (pressedMouseButtons & 4)
|
||||
state.middleButtonDown = true;
|
||||
|
||||
NSEventModifierFlags mod = event.modifierFlags();
|
||||
if (mod & NSControlKeyMask)
|
||||
state.ctrlPressed = true;
|
||||
if (mod & NSShiftKeyMask)
|
||||
state.shiftPressed = true;
|
||||
if (mod & NSAlternateKeyMask)
|
||||
state.altPressed = true;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void handleMouseWheel(NSEvent event)
|
||||
{
|
||||
int deltaX = cast(int)(0.5 + 10 * event.deltaX);
|
||||
int deltaY = cast(int)(0.5 + 10 * event.deltaY);
|
||||
Point mousePos = getMouseXY(_view, event, _height);
|
||||
_listener.onMouseWheel(mousePos.x, mousePos.y, deltaX, deltaY, getMouseState(event));
|
||||
}
|
||||
|
||||
void handleKeyEvent(NSEvent event, bool released)
|
||||
{
|
||||
uint keyCode = event.keyCode();
|
||||
uint key;
|
||||
switch (keyCode)
|
||||
{
|
||||
case kVK_ANSI_Keypad0: key = KeyCode.KEY_0; break;
|
||||
case kVK_ANSI_Keypad1: key = KeyCode.KEY_1; break;
|
||||
case kVK_ANSI_Keypad2: key = KeyCode.KEY_2; break;
|
||||
case kVK_ANSI_Keypad3: key = KeyCode.KEY_3; break;
|
||||
case kVK_ANSI_Keypad4: key = KeyCode.KEY_4; break;
|
||||
case kVK_ANSI_Keypad5: key = KeyCode.KEY_5; break;
|
||||
case kVK_ANSI_Keypad6: key = KeyCode.KEY_6; break;
|
||||
case kVK_ANSI_Keypad7: key = KeyCode.KEY_7; break;
|
||||
case kVK_ANSI_Keypad8: key = KeyCode.KEY_8; break;
|
||||
case kVK_ANSI_Keypad9: key = KeyCode.KEY_9; break;
|
||||
case kVK_Return: key = KeyCode.RETURN; break;
|
||||
case kVK_Escape: key = KeyCode.ESCAPE; break;
|
||||
case kVK_LeftArrow: key = KeyCode.LEFT; break;
|
||||
case kVK_RightArrow: key = KeyCode.RIGHT; break;
|
||||
case kVK_DownArrow: key = KeyCode.DOWN; break;
|
||||
case kVK_UpArrow: key = KeyCode.UP; break;
|
||||
default: key = 0;
|
||||
}
|
||||
|
||||
if (released)
|
||||
_listener.onKeyDown(key);
|
||||
else
|
||||
_listener.onKeyUp(key);
|
||||
}
|
||||
|
||||
void handleMouseMove(NSEvent event)
|
||||
{
|
||||
Point mousePos = getMouseXY(_view, event, _height);
|
||||
|
||||
if (_firstMouseMove)
|
||||
{
|
||||
_firstMouseMove = false;
|
||||
_lastMouseX = mousePos.x;
|
||||
_lastMouseY = mousePos.y;
|
||||
}
|
||||
|
||||
_listener.onMouseMove(mousePos.x, mousePos.y, mousePos.x - _lastMouseX, mousePos.y - _lastMouseY,
|
||||
getMouseState(event));
|
||||
|
||||
_lastMouseX = mousePos.x;
|
||||
_lastMouseY = mousePos.y;
|
||||
}
|
||||
|
||||
void handleMouseClicks(NSEvent event, MouseButton mb, bool released)
|
||||
{
|
||||
Point mousePos = getMouseXY(_view, event, _height);
|
||||
|
||||
if (released)
|
||||
_listener.onMouseRelease(mousePos.x, mousePos.y, mb, getMouseState(event));
|
||||
else
|
||||
{
|
||||
int clickCount = event.clickCount();
|
||||
bool isDoubleClick = clickCount >= 2;
|
||||
_listener.onMouseClick(mousePos.x, mousePos.y, mb, isDoubleClick, getMouseState(event));
|
||||
}
|
||||
}
|
||||
|
||||
enum scanLineAlignment = 4; // could be anything
|
||||
|
||||
// given a width, how long in bytes should scanlines be
|
||||
int byteStride(int width)
|
||||
{
|
||||
int widthInBytes = width * 4;
|
||||
return (widthInBytes + (scanLineAlignment - 1)) & ~(scanLineAlignment-1);
|
||||
}
|
||||
|
||||
void drawRect(NSRect rect)
|
||||
{
|
||||
NSGraphicsContext nsContext = NSGraphicsContext.currentContext();
|
||||
|
||||
CIContext ciContext = nsContext.getCIContext();
|
||||
|
||||
// update internal buffers in case of startup/resize
|
||||
{
|
||||
NSRect boundsRect = _view.bounds();
|
||||
int width = cast(int)(boundsRect.size.width); // truncating down the dimensions of bounds
|
||||
int height = cast(int)(boundsRect.size.height);
|
||||
updateSizeIfNeeded(width, height);
|
||||
}
|
||||
|
||||
// The first drawRect callback occurs before the timer triggers.
|
||||
// But because recomputeDirtyAreas() wasn't called before there is nothing to draw.
|
||||
// Hence, do it.
|
||||
if (_dirtyAreasAreNotYetComputed)
|
||||
{
|
||||
_dirtyAreasAreNotYetComputed = false;
|
||||
_listener.recomputeDirtyAreas();
|
||||
}
|
||||
|
||||
// draw buffers
|
||||
// ImageRef!RGBA wfb;
|
||||
// wfb.w = _width;
|
||||
// wfb.h = _height;
|
||||
// wfb.pitch = byteStride(_width);
|
||||
// wfb.pixels = cast(RGBA*)_buffer;
|
||||
// _listener.onDraw(wfb, WindowPixelFormat.ARGB8);
|
||||
_drawBuf.fill(0x8090B0);
|
||||
_drawBuf.fillRect(Rect(20, 20, 120, 120), 0xFFBBBB);
|
||||
|
||||
size_t sizeNeeded = byteStride(_width) * _height;
|
||||
_imageData = NSData.dataWithBytesNoCopy(cast(ubyte*)_drawBuf.scanLine(0), sizeNeeded, false);
|
||||
|
||||
CIImage image = CIImage.imageWithBitmapData(_imageData,
|
||||
byteStride(_width),
|
||||
CGSize(_width, _height),
|
||||
kCIFormatARGB8,
|
||||
_cgColorSpaceRef);
|
||||
|
||||
ciContext.drawImage(image, rect, rect);
|
||||
}
|
||||
|
||||
/// Returns: true if window size changed.
|
||||
bool updateSizeIfNeeded(int newWidth, int newHeight)
|
||||
{
|
||||
// only do something if the client size has changed
|
||||
if ( (newWidth != _width) || (newHeight != _height) )
|
||||
{
|
||||
// Extends buffer
|
||||
if (_buffer != null)
|
||||
{
|
||||
free(_buffer);
|
||||
_buffer = null;
|
||||
}
|
||||
|
||||
size_t sizeNeeded = byteStride(newWidth) * newHeight;
|
||||
_buffer = cast(ubyte*) malloc(sizeNeeded);
|
||||
_width = newWidth;
|
||||
_height = newHeight;
|
||||
if (_drawBuf is null)
|
||||
_drawBuf = new ColorDrawBuf(_width, _height);
|
||||
else if (_drawBuf.width != _width || _drawBuf.height != _height)
|
||||
_drawBuf.resize(_width, _height);
|
||||
_listener.onResized(_width, _height);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void doAnimation()
|
||||
{
|
||||
uint now = getTimeMs();
|
||||
double dt = (now - _lastMeasturedTimeInMs) * 0.001;
|
||||
double time = (now - _timeAtCreationInMs) * 0.001; // hopefully no plug-in will be open more than 49 days
|
||||
_lastMeasturedTimeInMs = now;
|
||||
_listener.onAnimate(dt, time);
|
||||
}
|
||||
|
||||
void onTimer()
|
||||
{
|
||||
// Deal with animation
|
||||
doAnimation();
|
||||
|
||||
_listener.recomputeDirtyAreas();
|
||||
_dirtyAreasAreNotYetComputed = false;
|
||||
Rect dirtyRect = _listener.getDirtyRectangle();
|
||||
if (!dirtyRect.empty())
|
||||
{
|
||||
|
||||
NSRect boundsRect = _view.bounds();
|
||||
int height = cast(int)(boundsRect.size.height);
|
||||
NSRect r = NSMakeRect(dirtyRect.left,
|
||||
height - dirtyRect.top - dirtyRect.height,
|
||||
dirtyRect.width,
|
||||
dirtyRect.height);
|
||||
_view.setNeedsDisplayInRect(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DPlugCustomView
|
||||
{
|
||||
// This class uses a unique class name for each plugin instance
|
||||
static string customClassName = null;
|
||||
|
||||
NSView parent;
|
||||
alias parent this;
|
||||
|
||||
// create from an id
|
||||
this (id id_)
|
||||
{
|
||||
this._id = id_;
|
||||
}
|
||||
|
||||
/// Allocates, but do not init
|
||||
static DPlugCustomView alloc()
|
||||
{
|
||||
alias fun_t = extern(C) id function (id obj, SEL sel);
|
||||
return DPlugCustomView( (cast(fun_t)objc_msgSend)(getClassID(), sel!"alloc") );
|
||||
}
|
||||
|
||||
static Class getClass()
|
||||
{
|
||||
return cast(Class)( getClassID() );
|
||||
}
|
||||
|
||||
static id getClassID()
|
||||
{
|
||||
assert(customClassName !is null);
|
||||
return objc_getClass(customClassName);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
CocoaWindow _window;
|
||||
NSTimer _timer = null;
|
||||
|
||||
void initialize(CocoaWindow window, int width, int height)
|
||||
{
|
||||
// Warning: taking this address is fishy since DPlugCustomView is a struct and thus could be copied
|
||||
// we rely on the fact it won't :|
|
||||
void* thisPointer = cast(void*)(&this);
|
||||
object_setInstanceVariable(_id, "this", thisPointer);
|
||||
|
||||
this._window = window;
|
||||
|
||||
NSRect r = NSRect(NSPoint(0, 0), NSSize(width, height));
|
||||
initWithFrame(r);
|
||||
|
||||
_timer = NSTimer.timerWithTimeInterval(1 / 60.0, this, sel!"onTimer:", null, true);
|
||||
NSRunLoop.currentRunLoop().addTimer(_timer, NSRunLoopCommonModes);
|
||||
}
|
||||
|
||||
static Class clazz;
|
||||
|
||||
static void registerSubclass()
|
||||
{
|
||||
clazz = objc_allocateClassPair(cast(Class) lazyClass!"NSView", toStringz(customClassName), 0);
|
||||
|
||||
class_addMethod(clazz, sel!"keyDown:", cast(IMP) &keyDown, "v@:@");
|
||||
class_addMethod(clazz, sel!"keyUp:", cast(IMP) &keyUp, "v@:@");
|
||||
class_addMethod(clazz, sel!"mouseDown:", cast(IMP) &mouseDown, "v@:@");
|
||||
class_addMethod(clazz, sel!"mouseUp:", cast(IMP) &mouseUp, "v@:@");
|
||||
class_addMethod(clazz, sel!"rightMouseDown:", cast(IMP) &rightMouseDown, "v@:@");
|
||||
class_addMethod(clazz, sel!"rightMouseUp:", cast(IMP) &rightMouseUp, "v@:@");
|
||||
class_addMethod(clazz, sel!"otherMouseDown:", cast(IMP) &otherMouseDown, "v@:@");
|
||||
class_addMethod(clazz, sel!"otherMouseUp:", cast(IMP) &otherMouseUp, "v@:@");
|
||||
class_addMethod(clazz, sel!"mouseMoved:", cast(IMP) &mouseMoved, "v@:@");
|
||||
class_addMethod(clazz, sel!"mouseDragged:", cast(IMP) &mouseMoved, "v@:@");
|
||||
class_addMethod(clazz, sel!"rightMouseDragged:", cast(IMP) &mouseMoved, "v@:@");
|
||||
class_addMethod(clazz, sel!"otherMouseDragged:", cast(IMP) &mouseMoved, "v@:@");
|
||||
class_addMethod(clazz, sel!"acceptsFirstResponder", cast(IMP) &acceptsFirstResponder, "b@:");
|
||||
class_addMethod(clazz, sel!"isOpaque", cast(IMP) &isOpaque, "b@:");
|
||||
class_addMethod(clazz, sel!"acceptsFirstMouse:", cast(IMP) &acceptsFirstMouse, "b@:@");
|
||||
class_addMethod(clazz, sel!"viewDidMoveToWindow", cast(IMP) &viewDidMoveToWindow, "v@:");
|
||||
class_addMethod(clazz, sel!"drawRect:", cast(IMP) &drawRect, "v@:" ~ encode!NSRect);
|
||||
class_addMethod(clazz, sel!"onTimer:", cast(IMP) &onTimer, "v@:@");
|
||||
|
||||
// This ~ is to avoid a strange DMD ICE. Didn't succeed in isolating it.
|
||||
class_addMethod(clazz, sel!("scroll" ~ "Wheel:") , cast(IMP) &scrollWheel, "v@:@");
|
||||
|
||||
// very important: add an instance variable for the this pointer so that the D object can be
|
||||
// retrieved from an id
|
||||
class_addIvar(clazz, "this", (void*).sizeof, (void*).sizeof == 4 ? 2 : 3, "^v");
|
||||
|
||||
objc_registerClassPair(clazz);
|
||||
}
|
||||
|
||||
static void unregisterSubclass()
|
||||
{
|
||||
// For some reason the class need to continue to exist, so we leak it
|
||||
// objc_disposeClassPair(clazz);
|
||||
// TODO: remove this crap
|
||||
}
|
||||
|
||||
void killTimer()
|
||||
{
|
||||
if (_timer)
|
||||
{
|
||||
_timer.invalidate();
|
||||
_timer = NSTimer(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DPlugCustomView getInstance(id anId)
|
||||
{
|
||||
// strange thing: object_getInstanceVariable definition is odd (void**)
|
||||
// and only works for pointer-sized values says SO
|
||||
void* thisPointer = null;
|
||||
Ivar var = object_getInstanceVariable(anId, "this", &thisPointer);
|
||||
assert(var !is null);
|
||||
assert(thisPointer !is null);
|
||||
return *cast(DPlugCustomView*)thisPointer;
|
||||
}
|
||||
|
||||
Point getMouseXY(NSView view, NSEvent event, int windowHeight)
|
||||
{
|
||||
NSPoint mouseLocation = event.locationInWindow();
|
||||
mouseLocation = view.convertPoint(mouseLocation, NSView(null));
|
||||
int px = cast(int)(mouseLocation.x) - 2;
|
||||
int py = windowHeight - cast(int)(mouseLocation.y) - 3;
|
||||
return Point(px, py);
|
||||
}
|
||||
|
||||
// Overridden function gets called with an id, instead of the self pointer.
|
||||
// So we have to get back the D class object address.
|
||||
// Big thanks to Mike Ash (@macdev)
|
||||
extern(C)
|
||||
{
|
||||
void keyDown(id self, SEL selector, id event)
|
||||
{
|
||||
//FPControl fpctrl;
|
||||
//fpctrl.initialize();
|
||||
DPlugCustomView view = getInstance(self);
|
||||
view._window.handleKeyEvent(NSEvent(event), false);
|
||||
}
|
||||
|
||||
void keyUp(id self, SEL selector, id event)
|
||||
{
|
||||
//FPControl fpctrl;
|
||||
//fpctrl.initialize();
|
||||
DPlugCustomView view = getInstance(self);
|
||||
view._window.handleKeyEvent(NSEvent(event), true);
|
||||
}
|
||||
|
||||
void mouseDown(id self, SEL selector, id event)
|
||||
{
|
||||
//FPControl fpctrl;
|
||||
//fpctrl.initialize();
|
||||
DPlugCustomView view = getInstance(self);
|
||||
view._window.handleMouseClicks(NSEvent(event), MouseButton.left, false);
|
||||
}
|
||||
|
||||
void mouseUp(id self, SEL selector, id event)
|
||||
{
|
||||
//FPControl fpctrl;
|
||||
//fpctrl.initialize();
|
||||
DPlugCustomView view = getInstance(self);
|
||||
view._window.handleMouseClicks(NSEvent(event), MouseButton.left, true);
|
||||
}
|
||||
|
||||
void rightMouseDown(id self, SEL selector, id event)
|
||||
{
|
||||
//FPControl fpctrl;
|
||||
//fpctrl.initialize();
|
||||
DPlugCustomView view = getInstance(self);
|
||||
view._window.handleMouseClicks(NSEvent(event), MouseButton.right, false);
|
||||
}
|
||||
|
||||
void rightMouseUp(id self, SEL selector, id event)
|
||||
{
|
||||
//FPControl fpctrl;
|
||||
//fpctrl.initialize();
|
||||
DPlugCustomView view = getInstance(self);
|
||||
view._window.handleMouseClicks(NSEvent(event), MouseButton.right, true);
|
||||
}
|
||||
|
||||
void otherMouseDown(id self, SEL selector, id event)
|
||||
{
|
||||
//FPControl fpctrl;
|
||||
//fpctrl.initialize();
|
||||
DPlugCustomView view = getInstance(self);
|
||||
auto nsEvent = NSEvent(event);
|
||||
if (nsEvent.buttonNumber == 2)
|
||||
view._window.handleMouseClicks(nsEvent, MouseButton.middle, false);
|
||||
}
|
||||
|
||||
void otherMouseUp(id self, SEL selector, id event)
|
||||
{
|
||||
//FPControl fpctrl;
|
||||
//fpctrl.initialize();
|
||||
DPlugCustomView view = getInstance(self);
|
||||
auto nsEvent = NSEvent(event);
|
||||
if (nsEvent.buttonNumber == 2)
|
||||
view._window.handleMouseClicks(nsEvent, MouseButton.middle, true);
|
||||
}
|
||||
|
||||
void mouseMoved(id self, SEL selector, id event)
|
||||
{
|
||||
//FPControl fpctrl;
|
||||
//fpctrl.initialize();
|
||||
DPlugCustomView view = getInstance(self);
|
||||
view._window.handleMouseMove(NSEvent(event));
|
||||
}
|
||||
|
||||
void scrollWheel(id self, SEL selector, id event)
|
||||
{
|
||||
//FPControl fpctrl;
|
||||
//fpctrl.initialize();
|
||||
DPlugCustomView view = getInstance(self);
|
||||
view._window.handleMouseWheel(NSEvent(event));
|
||||
}
|
||||
|
||||
bool acceptsFirstResponder(id self, SEL selector)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
bool acceptsFirstMouse(id self, SEL selector, id pEvent)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
bool isOpaque(id self, SEL selector)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
void viewDidMoveToWindow(id self, SEL selector)
|
||||
{
|
||||
DPlugCustomView view = getInstance(self);
|
||||
NSWindow parentWindow = view.window();
|
||||
if (parentWindow)
|
||||
{
|
||||
parentWindow.makeFirstResponder(view);
|
||||
parentWindow.setAcceptsMouseMovedEvents(true);
|
||||
}
|
||||
}
|
||||
|
||||
void drawRect(id self, SEL selector, NSRect rect)
|
||||
{
|
||||
//FPControl fpctrl;
|
||||
//fpctrl.initialize();
|
||||
DPlugCustomView view = getInstance(self);
|
||||
view._window.drawRect(rect);
|
||||
}
|
||||
|
||||
void onTimer(id self, SEL selector, id timer)
|
||||
{
|
||||
//FPControl fpctrl;
|
||||
//fpctrl.initialize();
|
||||
DPlugCustomView view = getInstance(self);
|
||||
view._window.onTimer();
|
||||
}
|
||||
}
|
|
@ -162,6 +162,22 @@
|
|||
-Jviews/res/hdpi
|
||||
-Jviews/res/mdpi
|
||||
-Jviews/res/i18n
|
||||
</ExtraCompilerArguments>
|
||||
<UnittestMode>false</UnittestMode>
|
||||
<OutputName>dmledit-monod-linux</OutputName>
|
||||
<Target>Executable</Target>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<DebugLevel>0</DebugLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugX11|AnyCPU' ">
|
||||
<OutputPath>bin\DebugX11</OutputPath>
|
||||
<ObjectsDirectory>obj/DebugX11</ObjectsDirectory>
|
||||
<LinkinThirdPartyLibraries>false</LinkinThirdPartyLibraries>
|
||||
<ExtraCompilerArguments>-Jviews
|
||||
-Jviews/res
|
||||
-Jviews/res/hdpi
|
||||
-Jviews/res/mdpi
|
||||
-Jviews/res/i18n
|
||||
</ExtraCompilerArguments>
|
||||
<UnittestMode>false</UnittestMode>
|
||||
<OutputName>dmledit-monod-linux</OutputName>
|
||||
|
|
|
@ -146,17 +146,32 @@ class EditFrame : AppFrame {
|
|||
}
|
||||
}
|
||||
|
||||
void saveSourceFile(string filename) {
|
||||
if (filename.length == 0)
|
||||
filename = _filename;
|
||||
import std.file;
|
||||
_filename = filename;
|
||||
window.windowCaption = toUTF32(filename);
|
||||
_editor.save(filename);
|
||||
}
|
||||
|
||||
bool onCanClose() {
|
||||
// todo
|
||||
return true;
|
||||
}
|
||||
|
||||
FileDialog createFileDialog(UIString caption) {
|
||||
FileDialog dlg = new FileDialog(caption, window, null);
|
||||
FileDialog createFileDialog(UIString caption, bool fileMustExist = true) {
|
||||
uint flags = DialogFlag.Modal | DialogFlag.Resizable;
|
||||
if (fileMustExist)
|
||||
flags |= FileDialogFlag.FileMustExist;
|
||||
FileDialog dlg = new FileDialog(caption, window, null, flags);
|
||||
dlg.filetypeIcons[".d"] = "text-dml";
|
||||
return dlg;
|
||||
}
|
||||
|
||||
void saveAs() {
|
||||
}
|
||||
|
||||
/// override to handle specific actions
|
||||
override bool handleAction(const Action a) {
|
||||
if (a) {
|
||||
|
@ -169,7 +184,40 @@ class EditFrame : AppFrame {
|
|||
window.showMessageBox(UIString("About DlangUI ML Editor"d),
|
||||
UIString("DLangIDE\n(C) Vadim Lopatin, 2015\nhttp://github.com/buggins/dlangui\nSimple editor for DML code"d));
|
||||
return true;
|
||||
case IDEActions.FileOpen:
|
||||
case IDEActions.FileNew:
|
||||
UIString caption;
|
||||
caption = "Create new DML file"d;
|
||||
FileDialog dlg = createFileDialog(caption, false);
|
||||
dlg.addFilter(FileFilterEntry(UIString("DML files"d), "*.dml"));
|
||||
dlg.addFilter(FileFilterEntry(UIString("All files"d), "*.*"));
|
||||
dlg.onDialogResult = delegate(Dialog dlg, const Action result) {
|
||||
if (result.id == ACTION_OPEN.id) {
|
||||
string filename = result.stringParam;
|
||||
_editor.text=""d;
|
||||
saveSourceFile(filename);
|
||||
}
|
||||
};
|
||||
dlg.show();
|
||||
return true;
|
||||
case IDEActions.FileSave:
|
||||
if (_filename.length) {
|
||||
saveSourceFile(_filename);
|
||||
return true;
|
||||
}
|
||||
UIString caption;
|
||||
caption = "Save DML File as"d;
|
||||
FileDialog dlg = createFileDialog(caption, false);
|
||||
dlg.addFilter(FileFilterEntry(UIString("DML files"d), "*.dml"));
|
||||
dlg.addFilter(FileFilterEntry(UIString("All files"d), "*.*"));
|
||||
dlg.onDialogResult = delegate(Dialog dlg, const Action result) {
|
||||
if (result.id == ACTION_OPEN.id) {
|
||||
string filename = result.stringParam;
|
||||
saveSourceFile(filename);
|
||||
}
|
||||
};
|
||||
dlg.show();
|
||||
return true;
|
||||
case IDEActions.FileOpen:
|
||||
UIString caption;
|
||||
caption = "Open DML File"d;
|
||||
FileDialog dlg = createFileDialog(caption);
|
||||
|
@ -196,7 +244,23 @@ class EditFrame : AppFrame {
|
|||
return false;
|
||||
}
|
||||
|
||||
void updatePreview() {
|
||||
/// override to handle specific actions state (e.g. change enabled state for supported actions)
|
||||
override bool handleActionStateRequest(const Action a) {
|
||||
switch (a.id) {
|
||||
case IDEActions.HelpAbout:
|
||||
case IDEActions.FileNew:
|
||||
case IDEActions.FileSave:
|
||||
case IDEActions.FileOpen:
|
||||
case IDEActions.DebugStart:
|
||||
case IDEActions.EditPreferences:
|
||||
a.state = ACTION_STATE_ENABLED;
|
||||
return true;
|
||||
default:
|
||||
return super.handleActionStateRequest(a);
|
||||
}
|
||||
}
|
||||
|
||||
void updatePreview() {
|
||||
dstring dsource = _editor.text;
|
||||
string source = toUTF8(dsource);
|
||||
try {
|
||||
|
|
|
@ -161,6 +161,22 @@
|
|||
-Jviews/res/hdpi
|
||||
-Jviews/res/mdpi
|
||||
-Jviews/res/i18n
|
||||
</ExtraCompilerArguments>
|
||||
<UnittestMode>false</UnittestMode>
|
||||
<OutputName>example1-monod-linux</OutputName>
|
||||
<Target>Executable</Target>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<DebugLevel>0</DebugLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugX11|AnyCPU' ">
|
||||
<OutputPath>bin\DebugX11</OutputPath>
|
||||
<ObjectsDirectory>obj/DebugX11</ObjectsDirectory>
|
||||
<LinkinThirdPartyLibraries>false</LinkinThirdPartyLibraries>
|
||||
<ExtraCompilerArguments>-Jviews
|
||||
-Jviews/res
|
||||
-Jviews/res/hdpi
|
||||
-Jviews/res/mdpi
|
||||
-Jviews/res/i18n
|
||||
</ExtraCompilerArguments>
|
||||
<UnittestMode>false</UnittestMode>
|
||||
<OutputName>example1-monod-linux</OutputName>
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
<Target>Executable</Target>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<DebugLevel>0</DebugLevel>
|
||||
<ExtraLinkerArguments>-v</ExtraLinkerArguments>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
|
@ -64,6 +64,7 @@
|
|||
<Target>Executable</Target>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<DebugLevel>0</DebugLevel>
|
||||
<ExtraLinkerArguments>-v</ExtraLinkerArguments>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Unittest|x64' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -84,6 +85,7 @@
|
|||
<Target>Executable</Target>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<DebugLevel>0</DebugLevel>
|
||||
<ExtraLinkerArguments>-v</ExtraLinkerArguments>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="src\example1.d" />
|
||||
|
|
|
@ -129,6 +129,27 @@
|
|||
<Externalconsole>true</Externalconsole>
|
||||
<DebugLevel>0</DebugLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugX11|x64' ">
|
||||
<OutputPath>bin\DebugX11</OutputPath>
|
||||
<VersionIds>
|
||||
<VersionIds>
|
||||
<String>USE_X11</String>
|
||||
<String>USE_FREETYPE</String>
|
||||
</VersionIds>
|
||||
</VersionIds>
|
||||
<ObjectsDirectory>obj/DebugX11</ObjectsDirectory>
|
||||
<LinkinThirdPartyLibraries>true</LinkinThirdPartyLibraries>
|
||||
<UnittestMode>false</UnittestMode>
|
||||
<OutputName>helloworld-monod-linux</OutputName>
|
||||
<Target>Executable</Target>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<DebugLevel>0</DebugLevel>
|
||||
<Libs>
|
||||
<Libs>
|
||||
<Lib>-L-lX11</Lib>
|
||||
</Libs>
|
||||
</Libs>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="src\helloworld.d" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -161,6 +161,22 @@
|
|||
-Jviews/res/hdpi
|
||||
-Jviews/res/mdpi
|
||||
-Jviews/res/i18n
|
||||
</ExtraCompilerArguments>
|
||||
<UnittestMode>false</UnittestMode>
|
||||
<OutputName>tetris-monod-linux</OutputName>
|
||||
<Target>Executable</Target>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<DebugLevel>0</DebugLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugX11|AnyCPU' ">
|
||||
<OutputPath>bin\DebugX11</OutputPath>
|
||||
<ObjectsDirectory>obj/DebugX11</ObjectsDirectory>
|
||||
<LinkinThirdPartyLibraries>false</LinkinThirdPartyLibraries>
|
||||
<ExtraCompilerArguments>-Jviews
|
||||
-Jviews/res
|
||||
-Jviews/res/hdpi
|
||||
-Jviews/res/mdpi
|
||||
-Jviews/res/i18n
|
||||
</ExtraCompilerArguments>
|
||||
<UnittestMode>false</UnittestMode>
|
||||
<OutputName>tetris-monod-linux</OutputName>
|
||||
|
|
|
@ -197,6 +197,28 @@ class NumberEditItem : SettingsItem {
|
|||
}
|
||||
}
|
||||
|
||||
class StringEditItem : SettingsItem {
|
||||
string _defaultValue;
|
||||
this(string id, UIString label, string defaultValue) {
|
||||
super(id, label);
|
||||
_defaultValue = defaultValue;
|
||||
}
|
||||
/// create setting widget
|
||||
override Widget[] createWidgets(Setting settings) {
|
||||
TextWidget lbl = new TextWidget(_id ~ "-label", _label);
|
||||
EditLine ed = new EditLine(_id ~ "-edit", _label);
|
||||
Setting setting = settings.settingByPath(_id, SettingType.STRING);
|
||||
string value = setting.strDef(_defaultValue);
|
||||
setting.str = value;
|
||||
ed.text = toUTF32(value);
|
||||
ed.onContentChangeListener = delegate(EditableContent content) {
|
||||
string value = toUTF8(content.text);
|
||||
setting.str = value;
|
||||
};
|
||||
return [lbl, ed];
|
||||
}
|
||||
}
|
||||
|
||||
/// settings page - item of settings tree, can edit several settings
|
||||
class SettingsPage {
|
||||
protected SettingsPage _parent;
|
||||
|
@ -261,7 +283,14 @@ class SettingsPage {
|
|||
return res;
|
||||
}
|
||||
|
||||
StringComboBoxItem addStringComboBox(string id, UIString label, StringListValue[] items) {
|
||||
/// add EditLine to edit string
|
||||
StringEditItem addStringEdit(string id, UIString label, string defaultValue = "") {
|
||||
StringEditItem res = new StringEditItem(id, label, defaultValue);
|
||||
addItem(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
StringComboBoxItem addStringComboBox(string id, UIString label, StringListValue[] items) {
|
||||
StringComboBoxItem res = new StringComboBoxItem(id, label, items);
|
||||
addItem(res);
|
||||
return res;
|
||||
|
|
|
@ -27,6 +27,22 @@ import std.conv;
|
|||
import std.string;
|
||||
import std.array;
|
||||
|
||||
derelict.util.exception.ShouldThrow gl3MissingSymFunc( string symName ) {
|
||||
import std.algorithm : equal;
|
||||
foreach(s; ["glGetError", "glShaderSource", "glCompileShader",
|
||||
"glGetShaderiv", "glGetShaderInfoLog", "glGetString",
|
||||
"glCreateProgram", "glUseProgram", "glDeleteProgram",
|
||||
"glDeleteShader", "glEnable", "glDisable", "glBlendFunc",
|
||||
"glUniformMatrix4fv", "glGetAttribLocation", "glGetUniformLocation",
|
||||
"glGenVertexArrays", "glBindVertexArray", "glBufferData",
|
||||
"glBindBuffer", "glBufferSubData"]) {
|
||||
if (symName.equal(s)) // Symbol is used
|
||||
return derelict.util.exception.ShouldThrow.Yes;
|
||||
}
|
||||
// Don't throw for unused symbol
|
||||
return derelict.util.exception.ShouldThrow.No;
|
||||
}
|
||||
|
||||
// utility function to fill 4-float array of vertex colors with converted CR 32bit color
|
||||
private void LVGLFillColor(uint color, float * buf, int count) {
|
||||
float r = ((color >> 16) & 255) / 255.0f;
|
||||
|
@ -85,8 +101,11 @@ class GLProgram {
|
|||
}
|
||||
|
||||
private void compatibilityFixes(ref char[] code, GLuint type) {
|
||||
if (glslversionInt < 150)
|
||||
if (glslversionInt < 150) {
|
||||
code = replace(code, " texture(", " texture2D(");
|
||||
code = replace(code, "in ", "");
|
||||
code = replace(code, "out ", "");
|
||||
}
|
||||
}
|
||||
|
||||
private GLuint compileShader(string src, GLuint type) {
|
||||
|
@ -277,11 +296,17 @@ class SolidFillProgram : GLProgram {
|
|||
|
||||
matrixLocation = glGetUniformLocation(program, "matrix");
|
||||
checkError("glGetUniformLocation matrix");
|
||||
if (matrixLocation == 0)
|
||||
Log.e("glGetUniformLocation failed for matrixLocation");
|
||||
vertexLocation = glGetAttribLocation(program, "vertex");
|
||||
checkError("glGetAttribLocation vertex");
|
||||
colAttrLocation = glGetAttribLocation(program, "colAttr");
|
||||
if (vertexLocation == 0)
|
||||
Log.e("glGetUniformLocation failed for vertexLocation");
|
||||
colAttrLocation = glGetAttribLocation(program, "colAttr");
|
||||
checkError("glGetAttribLocation colAttr");
|
||||
return res && matrixLocation >= 0 && vertexLocation >= 0 && colAttrLocation >= 0;
|
||||
if (colAttrLocation == 0)
|
||||
Log.e("glGetUniformLocation failed for colAttrLocation");
|
||||
return res && matrixLocation >= 0 && vertexLocation >= 0 && colAttrLocation >= 0;
|
||||
}
|
||||
|
||||
bool execute(float[] vertices, float[] colors) {
|
||||
|
|
|
@ -32,6 +32,10 @@ private import std.algorithm;
|
|||
private import core.sync.mutex;
|
||||
private import std.string;
|
||||
|
||||
/// entry point - declare such function to use as main for dlangui app
|
||||
extern(C) int UIAppMain(string[] args);
|
||||
|
||||
|
||||
// specify debug=DebugMouseEvents for logging mouse handling
|
||||
// specify debug=DebugRedraw for logging drawing and layouts handling
|
||||
// specify debug=DebugKeys for logging of key events
|
||||
|
@ -175,6 +179,10 @@ class Window {
|
|||
if (_mainWidget !is null)
|
||||
_mainWidget.window = this;
|
||||
}
|
||||
|
||||
// Abstract methods : override in platform implementatino
|
||||
|
||||
/// show window
|
||||
abstract void show();
|
||||
/// returns window caption
|
||||
abstract @property dstring windowCaption();
|
||||
|
@ -1370,6 +1378,9 @@ version (Windows) {
|
|||
/// put "mixin APP_ENTRY_POINT;" to main module of your dlangui based app
|
||||
mixin template APP_ENTRY_POINT() {
|
||||
version (linux) {
|
||||
version(USE_X11) {
|
||||
pragma(lib, "X11");
|
||||
}
|
||||
version (USE_XCB) {
|
||||
//pragma(lib, "png");
|
||||
pragma(lib, "xcb");
|
||||
|
@ -1404,217 +1415,12 @@ mixin template APP_ENTRY_POINT() {
|
|||
}
|
||||
}
|
||||
|
||||
version (Windows) {
|
||||
|
||||
/// initialize font manager - default implementation
|
||||
/// On win32 - first it tries to init freetype, and falls back to win32 fonts.
|
||||
/// On linux/mac - tries to init freetype with some hardcoded font paths
|
||||
bool initFontManager() {
|
||||
import win32.windows;
|
||||
import std.utf;
|
||||
import dlangui.platforms.windows.win32fonts;
|
||||
try {
|
||||
/// testing freetype font manager
|
||||
version(USE_FREETYPE) {
|
||||
Log.v("Trying to init FreeType font manager");
|
||||
|
||||
import dlangui.graphics.ftfonts;
|
||||
// trying to create font manager
|
||||
Log.v("Creating FreeTypeFontManager");
|
||||
FreeTypeFontManager ftfontMan = new FreeTypeFontManager();
|
||||
|
||||
import win32.shlobj;
|
||||
string fontsPath = "c:\\Windows\\Fonts\\";
|
||||
static if (true) { // SHGetFolderPathW not found in shell32.lib
|
||||
WCHAR[MAX_PATH] szPath;
|
||||
static if (false) {
|
||||
const CSIDL_FLAG_NO_ALIAS = 0x1000;
|
||||
const CSIDL_FLAG_DONT_UNEXPAND = 0x2000;
|
||||
if(SUCCEEDED(SHGetFolderPathW(NULL,
|
||||
CSIDL_FONTS|CSIDL_FLAG_NO_ALIAS|CSIDL_FLAG_DONT_UNEXPAND,
|
||||
NULL,
|
||||
0,
|
||||
szPath.ptr)))
|
||||
{
|
||||
fontsPath = toUTF8(fromWStringz(szPath));
|
||||
}
|
||||
} else {
|
||||
if (GetWindowsDirectory(szPath.ptr, MAX_PATH - 1)) {
|
||||
fontsPath = toUTF8(fromWStringz(szPath));
|
||||
Log.i("Windows directory: ", fontsPath);
|
||||
fontsPath ~= "\\Fonts\\";
|
||||
Log.i("Fonts directory: ", fontsPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.v("Registering fonts");
|
||||
ftfontMan.registerFont(fontsPath ~ "arial.ttf", FontFamily.SansSerif, "Arial", false, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "arialbd.ttf", FontFamily.SansSerif, "Arial", false, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "arialbi.ttf", FontFamily.SansSerif, "Arial", true, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "ariali.ttf", FontFamily.SansSerif, "Arial", true, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "cour.ttf", FontFamily.MonoSpace, "Courier New", false, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "courbd.ttf", FontFamily.MonoSpace, "Courier New", false, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "courbi.ttf", FontFamily.MonoSpace, "Courier New", true, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "couri.ttf", FontFamily.MonoSpace, "Courier New", true, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "times.ttf", FontFamily.Serif, "Times New Roman", false, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "timesbd.ttf", FontFamily.Serif, "Times New Roman", false, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "timesbi.ttf", FontFamily.Serif, "Times New Roman", true, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "timesi.ttf", FontFamily.Serif, "Times New Roman", true, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "consola.ttf", FontFamily.MonoSpace, "Consolas", false, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "consolab.ttf", FontFamily.MonoSpace, "Consolas", false, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "consolai.ttf", FontFamily.MonoSpace, "Consolas", true, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "consolaz.ttf", FontFamily.MonoSpace, "Consolas", true, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "verdana.ttf", FontFamily.SansSerif, "Verdana", false, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "verdanab.ttf", FontFamily.SansSerif, "Verdana", false, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "verdanai.ttf", FontFamily.SansSerif, "Verdana", true, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "verdanaz.ttf", FontFamily.SansSerif, "Verdana", true, FontWeight.Bold);
|
||||
if (ftfontMan.registeredFontCount()) {
|
||||
FontManager.instance = ftfontMan;
|
||||
} else {
|
||||
Log.w("No fonts registered in FreeType font manager. Disabling FreeType.");
|
||||
destroy(ftfontMan);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("Cannot create FreeTypeFontManager - falling back to win32");
|
||||
}
|
||||
|
||||
// use Win32 font manager
|
||||
if (FontManager.instance is null) {
|
||||
FontManager.instance = new Win32FontManager();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} else {
|
||||
import dlangui.graphics.ftfonts;
|
||||
bool registerFonts(FreeTypeFontManager ft, string path) {
|
||||
import std.file;
|
||||
if (!exists(path) || !isDir(path))
|
||||
return false;
|
||||
ft.registerFont(path ~ "DejaVuSans.ttf", FontFamily.SansSerif, "DejaVuSans", false, FontWeight.Normal);
|
||||
ft.registerFont(path ~ "DejaVuSans-Bold.ttf", FontFamily.SansSerif, "DejaVuSans", false, FontWeight.Bold);
|
||||
ft.registerFont(path ~ "DejaVuSans-Oblique.ttf", FontFamily.SansSerif, "DejaVuSans", true, FontWeight.Normal);
|
||||
ft.registerFont(path ~ "DejaVuSans-BoldOblique.ttf", FontFamily.SansSerif, "DejaVuSans", true, FontWeight.Bold);
|
||||
ft.registerFont(path ~ "DejaVuSansMono.ttf", FontFamily.MonoSpace, "DejaVuSansMono", false, FontWeight.Normal);
|
||||
ft.registerFont(path ~ "DejaVuSansMono-Bold.ttf", FontFamily.MonoSpace, "DejaVuSansMono", false, FontWeight.Bold);
|
||||
ft.registerFont(path ~ "DejaVuSansMono-Oblique.ttf", FontFamily.MonoSpace, "DejaVuSansMono", true, FontWeight.Normal);
|
||||
ft.registerFont(path ~ "DejaVuSansMono-BoldOblique.ttf", FontFamily.MonoSpace, "DejaVuSansMono", true, FontWeight.Bold);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// initialize font manager - default implementation
|
||||
/// On win32 - first it tries to init freetype, and falls back to win32 fonts.
|
||||
/// On linux/mac - tries to init freetype with some hardcoded font paths
|
||||
bool initFontManager() {
|
||||
FreeTypeFontManager ft = new FreeTypeFontManager();
|
||||
|
||||
if (!registerFontConfigFonts(ft)) {
|
||||
// TODO: use FontConfig
|
||||
Log.w("No fonts found using FontConfig. Trying hardcoded paths.");
|
||||
ft.registerFonts("/usr/share/fonts/truetype/dejavu/");
|
||||
ft.registerFonts("/usr/share/fonts/TTF/");
|
||||
ft.registerFonts("/usr/share/fonts/dejavu/");
|
||||
ft.registerFonts("/usr/share/fonts/truetype/ttf-dejavu/"); // let it compile on Debian Wheezy
|
||||
version(OSX) {
|
||||
ft.registerFont("/Library/Fonts/Arial.ttf", FontFamily.SansSerif, "Arial", false, FontWeight.Normal);
|
||||
ft.registerFont("/Library/Fonts/Arial Bold.ttf", FontFamily.SansSerif, "Arial", false, FontWeight.Bold);
|
||||
ft.registerFont("/Library/Fonts/Arial Italic.ttf", FontFamily.SansSerif, "Arial", true, FontWeight.Normal);
|
||||
ft.registerFont("/Library/Fonts/Arial Bold Italic.ttf", FontFamily.SansSerif, "Arial", true, FontWeight.Bold);
|
||||
ft.registerFont("/Library/Fonts/Arial Narrow.ttf", FontFamily.SansSerif, "Arial Narrow", false, FontWeight.Normal);
|
||||
ft.registerFont("/Library/Fonts/Arial Narrow Bold.ttf", FontFamily.SansSerif, "Arial Narrow", false, FontWeight.Bold);
|
||||
ft.registerFont("/Library/Fonts/Arial Narrow Italic.ttf", FontFamily.SansSerif, "Arial Narrow", true, FontWeight.Normal);
|
||||
ft.registerFont("/Library/Fonts/Arial Narrow Bold Italic.ttf", FontFamily.SansSerif, "Arial Narrow", true, FontWeight.Bold);
|
||||
ft.registerFont("/Library/Fonts/Courier New.ttf", FontFamily.MonoSpace, "Courier New", false, FontWeight.Normal);
|
||||
ft.registerFont("/Library/Fonts/Courier New Bold.ttf", FontFamily.MonoSpace, "Courier New", false, FontWeight.Bold);
|
||||
ft.registerFont("/Library/Fonts/Courier New Italic.ttf", FontFamily.MonoSpace, "Courier New", true, FontWeight.Normal);
|
||||
ft.registerFont("/Library/Fonts/Courier New Bold Italic.ttf", FontFamily.MonoSpace, "Courier New", true, FontWeight.Bold);
|
||||
ft.registerFont("/Library/Fonts/Georgia.ttf", FontFamily.SansSerif, "Georgia", false, FontWeight.Normal);
|
||||
ft.registerFont("/Library/Fonts/Georgia Bold.ttf", FontFamily.SansSerif, "Georgia", false, FontWeight.Bold);
|
||||
ft.registerFont("/Library/Fonts/Georgia Italic.ttf", FontFamily.SansSerif, "Georgia", true, FontWeight.Normal);
|
||||
ft.registerFont("/Library/Fonts/Georgia Bold Italic.ttf", FontFamily.SansSerif, "Georgia", true, FontWeight.Bold);
|
||||
ft.registerFont("/Library/Fonts/Georgia.ttf", FontFamily.SansSerif, "Georgia", false, FontWeight.Normal);
|
||||
ft.registerFont("/Library/Fonts/Georgia Bold.ttf", FontFamily.SansSerif, "Georgia", false, FontWeight.Bold);
|
||||
ft.registerFont("/Library/Fonts/Georgia Italic.ttf", FontFamily.SansSerif, "Georgia", true, FontWeight.Normal);
|
||||
ft.registerFont("/Library/Fonts/Georgia Bold Italic.ttf", FontFamily.SansSerif, "Georgia", true, FontWeight.Bold);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ft.registeredFontCount)
|
||||
return false;
|
||||
|
||||
FontManager.instance = ft;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// call this when all resources are supposed to be freed to report counts of non-freed resources by type
|
||||
void releaseResourcesOnAppExit() {
|
||||
|
||||
//
|
||||
debug setAppShuttingDownFlag();
|
||||
|
||||
debug {
|
||||
if (Widget.instanceCount() > 0) {
|
||||
Log.e("Non-zero Widget instance count when exiting: ", Widget.instanceCount);
|
||||
}
|
||||
}
|
||||
|
||||
currentTheme = null;
|
||||
drawableCache = null;
|
||||
imageCache = null;
|
||||
FontManager.instance = null;
|
||||
|
||||
debug {
|
||||
if (DrawBuf.instanceCount > 0) {
|
||||
Log.e("Non-zero DrawBuf instance count when exiting: ", DrawBuf.instanceCount);
|
||||
}
|
||||
if (Style.instanceCount > 0) {
|
||||
Log.e("Non-zero Style instance count when exiting: ", Style.instanceCount);
|
||||
}
|
||||
if (ImageDrawable.instanceCount > 0) {
|
||||
Log.e("Non-zero ImageDrawable instance count when exiting: ", ImageDrawable.instanceCount);
|
||||
}
|
||||
if (Drawable.instanceCount > 0) {
|
||||
Log.e("Non-zero Drawable instance count when exiting: ", Drawable.instanceCount);
|
||||
}
|
||||
version (USE_FREETYPE) {
|
||||
import dlangui.graphics.ftfonts;
|
||||
if (FreeTypeFontFile.instanceCount > 0) {
|
||||
Log.e("Non-zero FreeTypeFontFile instance count when exiting: ", FreeTypeFontFile.instanceCount);
|
||||
}
|
||||
if (FreeTypeFont.instanceCount > 0) {
|
||||
Log.e("Non-zero FreeTypeFont instance count when exiting: ", FreeTypeFont.instanceCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// initialize font manager on startup
|
||||
extern(C) bool initFontManager();
|
||||
/// initialize logging (for win32 - to file ui.log, for other platforms - stderr; log level is TRACE for debug builds, and WARN for release builds)
|
||||
void initLogs() {
|
||||
version (Windows) {
|
||||
debug {
|
||||
Log.setFileLogger(new std.stdio.File("ui.log", "w"));
|
||||
} else {
|
||||
// no logging unless version ForceLogs is set
|
||||
version(ForceLogs) {
|
||||
Log.setFileLogger(new std.stdio.File("ui.log", "w"));
|
||||
Log.i("Logging to file ui.log");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.setStderrLogger();
|
||||
}
|
||||
debug {
|
||||
Log.setLogLevel(LogLevel.Trace);
|
||||
} else {
|
||||
version(ForceLogs) {
|
||||
Log.setLogLevel(LogLevel.Trace);
|
||||
Log.i("Log level: trace");
|
||||
} else {
|
||||
Log.setLogLevel(LogLevel.Warn);
|
||||
Log.i("Log level: warn");
|
||||
}
|
||||
}
|
||||
Log.i("Logger is initialized");
|
||||
}
|
||||
extern(C) void initLogs();
|
||||
/// call this when all resources are supposed to be freed to report counts of non-freed resources by type
|
||||
extern(C) void releaseResourcesOnAppExit();
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,223 @@
|
|||
module dlangui.platforms.common.startup;
|
||||
|
||||
public import dlangui.core.events;
|
||||
public import dlangui.widgets.styles;
|
||||
public import dlangui.graphics.fonts;
|
||||
public import dlangui.graphics.resources;
|
||||
public import dlangui.widgets.widget;
|
||||
|
||||
version(USE_FREETYPE) {
|
||||
public import dlangui.graphics.ftfonts;
|
||||
}
|
||||
|
||||
version (Windows) {
|
||||
|
||||
/// initialize font manager - default implementation
|
||||
/// On win32 - first it tries to init freetype, and falls back to win32 fonts.
|
||||
/// On linux/mac - tries to init freetype with some hardcoded font paths
|
||||
extern(C) bool initFontManager() {
|
||||
import win32.windows;
|
||||
import std.utf;
|
||||
import dlangui.platforms.windows.win32fonts;
|
||||
try {
|
||||
/// testing freetype font manager
|
||||
version(USE_FREETYPE) {
|
||||
Log.v("Trying to init FreeType font manager");
|
||||
|
||||
import dlangui.graphics.ftfonts;
|
||||
// trying to create font manager
|
||||
Log.v("Creating FreeTypeFontManager");
|
||||
FreeTypeFontManager ftfontMan = new FreeTypeFontManager();
|
||||
|
||||
import win32.shlobj;
|
||||
string fontsPath = "c:\\Windows\\Fonts\\";
|
||||
static if (true) { // SHGetFolderPathW not found in shell32.lib
|
||||
WCHAR[MAX_PATH] szPath;
|
||||
static if (false) {
|
||||
const CSIDL_FLAG_NO_ALIAS = 0x1000;
|
||||
const CSIDL_FLAG_DONT_UNEXPAND = 0x2000;
|
||||
if(SUCCEEDED(SHGetFolderPathW(NULL,
|
||||
CSIDL_FONTS|CSIDL_FLAG_NO_ALIAS|CSIDL_FLAG_DONT_UNEXPAND,
|
||||
NULL,
|
||||
0,
|
||||
szPath.ptr)))
|
||||
{
|
||||
fontsPath = toUTF8(fromWStringz(szPath));
|
||||
}
|
||||
} else {
|
||||
if (GetWindowsDirectory(szPath.ptr, MAX_PATH - 1)) {
|
||||
fontsPath = toUTF8(fromWStringz(szPath));
|
||||
Log.i("Windows directory: ", fontsPath);
|
||||
fontsPath ~= "\\Fonts\\";
|
||||
Log.i("Fonts directory: ", fontsPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.v("Registering fonts");
|
||||
ftfontMan.registerFont(fontsPath ~ "arial.ttf", FontFamily.SansSerif, "Arial", false, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "arialbd.ttf", FontFamily.SansSerif, "Arial", false, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "arialbi.ttf", FontFamily.SansSerif, "Arial", true, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "ariali.ttf", FontFamily.SansSerif, "Arial", true, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "cour.ttf", FontFamily.MonoSpace, "Courier New", false, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "courbd.ttf", FontFamily.MonoSpace, "Courier New", false, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "courbi.ttf", FontFamily.MonoSpace, "Courier New", true, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "couri.ttf", FontFamily.MonoSpace, "Courier New", true, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "times.ttf", FontFamily.Serif, "Times New Roman", false, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "timesbd.ttf", FontFamily.Serif, "Times New Roman", false, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "timesbi.ttf", FontFamily.Serif, "Times New Roman", true, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "timesi.ttf", FontFamily.Serif, "Times New Roman", true, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "consola.ttf", FontFamily.MonoSpace, "Consolas", false, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "consolab.ttf", FontFamily.MonoSpace, "Consolas", false, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "consolai.ttf", FontFamily.MonoSpace, "Consolas", true, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "consolaz.ttf", FontFamily.MonoSpace, "Consolas", true, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "verdana.ttf", FontFamily.SansSerif, "Verdana", false, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "verdanab.ttf", FontFamily.SansSerif, "Verdana", false, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "verdanai.ttf", FontFamily.SansSerif, "Verdana", true, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "verdanaz.ttf", FontFamily.SansSerif, "Verdana", true, FontWeight.Bold);
|
||||
if (ftfontMan.registeredFontCount()) {
|
||||
FontManager.instance = ftfontMan;
|
||||
} else {
|
||||
Log.w("No fonts registered in FreeType font manager. Disabling FreeType.");
|
||||
destroy(ftfontMan);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("Cannot create FreeTypeFontManager - falling back to win32");
|
||||
}
|
||||
|
||||
// use Win32 font manager
|
||||
if (FontManager.instance is null) {
|
||||
FontManager.instance = new Win32FontManager();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} else {
|
||||
import dlangui.graphics.ftfonts;
|
||||
bool registerFonts(FreeTypeFontManager ft, string path) {
|
||||
import std.file;
|
||||
if (!exists(path) || !isDir(path))
|
||||
return false;
|
||||
ft.registerFont(path ~ "DejaVuSans.ttf", FontFamily.SansSerif, "DejaVuSans", false, FontWeight.Normal);
|
||||
ft.registerFont(path ~ "DejaVuSans-Bold.ttf", FontFamily.SansSerif, "DejaVuSans", false, FontWeight.Bold);
|
||||
ft.registerFont(path ~ "DejaVuSans-Oblique.ttf", FontFamily.SansSerif, "DejaVuSans", true, FontWeight.Normal);
|
||||
ft.registerFont(path ~ "DejaVuSans-BoldOblique.ttf", FontFamily.SansSerif, "DejaVuSans", true, FontWeight.Bold);
|
||||
ft.registerFont(path ~ "DejaVuSansMono.ttf", FontFamily.MonoSpace, "DejaVuSansMono", false, FontWeight.Normal);
|
||||
ft.registerFont(path ~ "DejaVuSansMono-Bold.ttf", FontFamily.MonoSpace, "DejaVuSansMono", false, FontWeight.Bold);
|
||||
ft.registerFont(path ~ "DejaVuSansMono-Oblique.ttf", FontFamily.MonoSpace, "DejaVuSansMono", true, FontWeight.Normal);
|
||||
ft.registerFont(path ~ "DejaVuSansMono-BoldOblique.ttf", FontFamily.MonoSpace, "DejaVuSansMono", true, FontWeight.Bold);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// initialize font manager - default implementation
|
||||
/// On win32 - first it tries to init freetype, and falls back to win32 fonts.
|
||||
/// On linux/mac - tries to init freetype with some hardcoded font paths
|
||||
extern(C) bool initFontManager() {
|
||||
FreeTypeFontManager ft = new FreeTypeFontManager();
|
||||
|
||||
if (!registerFontConfigFonts(ft)) {
|
||||
// TODO: use FontConfig
|
||||
Log.w("No fonts found using FontConfig. Trying hardcoded paths.");
|
||||
ft.registerFonts("/usr/share/fonts/truetype/dejavu/");
|
||||
ft.registerFonts("/usr/share/fonts/TTF/");
|
||||
ft.registerFonts("/usr/share/fonts/dejavu/");
|
||||
ft.registerFonts("/usr/share/fonts/truetype/ttf-dejavu/"); // let it compile on Debian Wheezy
|
||||
version(OSX) {
|
||||
ft.registerFont("/Library/Fonts/Arial.ttf", FontFamily.SansSerif, "Arial", false, FontWeight.Normal);
|
||||
ft.registerFont("/Library/Fonts/Arial Bold.ttf", FontFamily.SansSerif, "Arial", false, FontWeight.Bold);
|
||||
ft.registerFont("/Library/Fonts/Arial Italic.ttf", FontFamily.SansSerif, "Arial", true, FontWeight.Normal);
|
||||
ft.registerFont("/Library/Fonts/Arial Bold Italic.ttf", FontFamily.SansSerif, "Arial", true, FontWeight.Bold);
|
||||
//ft.registerFont("/Library/Fonts/Arial Narrow.ttf", FontFamily.SansSerif, "Arial Narrow", false, FontWeight.Normal);
|
||||
//ft.registerFont("/Library/Fonts/Arial Narrow Bold.ttf", FontFamily.SansSerif, "Arial Narrow", false, FontWeight.Bold);
|
||||
//ft.registerFont("/Library/Fonts/Arial Narrow Italic.ttf", FontFamily.SansSerif, "Arial Narrow", true, FontWeight.Normal);
|
||||
//ft.registerFont("/Library/Fonts/Arial Narrow Bold Italic.ttf", FontFamily.SansSerif, "Arial Narrow", true, FontWeight.Bold);
|
||||
ft.registerFont("/Library/Fonts/Courier New.ttf", FontFamily.MonoSpace, "Courier New", false, FontWeight.Normal);
|
||||
ft.registerFont("/Library/Fonts/Courier New Bold.ttf", FontFamily.MonoSpace, "Courier New", false, FontWeight.Bold);
|
||||
ft.registerFont("/Library/Fonts/Courier New Italic.ttf", FontFamily.MonoSpace, "Courier New", true, FontWeight.Normal);
|
||||
ft.registerFont("/Library/Fonts/Courier New Bold Italic.ttf", FontFamily.MonoSpace, "Courier New", true, FontWeight.Bold);
|
||||
ft.registerFont("/Library/Fonts/Georgia.ttf", FontFamily.Serif, "Georgia", false, FontWeight.Normal);
|
||||
ft.registerFont("/Library/Fonts/Georgia Bold.ttf", FontFamily.Serif, "Georgia", false, FontWeight.Bold);
|
||||
ft.registerFont("/Library/Fonts/Georgia Italic.ttf", FontFamily.Serif, "Georgia", true, FontWeight.Normal);
|
||||
ft.registerFont("/Library/Fonts/Georgia Bold Italic.ttf", FontFamily.Serif, "Georgia", true, FontWeight.Bold);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ft.registeredFontCount)
|
||||
return false;
|
||||
|
||||
FontManager.instance = ft;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// initialize logging (for win32 - to file ui.log, for other platforms - stderr; log level is TRACE for debug builds, and WARN for release builds)
|
||||
extern (C) void initLogs() {
|
||||
version (Windows) {
|
||||
debug {
|
||||
Log.setFileLogger(new std.stdio.File("ui.log", "w"));
|
||||
} else {
|
||||
// no logging unless version ForceLogs is set
|
||||
version(ForceLogs) {
|
||||
Log.setFileLogger(new std.stdio.File("ui.log", "w"));
|
||||
Log.i("Logging to file ui.log");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.setStderrLogger();
|
||||
}
|
||||
debug {
|
||||
Log.setLogLevel(LogLevel.Trace);
|
||||
} else {
|
||||
version(ForceLogs) {
|
||||
Log.setLogLevel(LogLevel.Trace);
|
||||
Log.i("Log level: trace");
|
||||
} else {
|
||||
Log.setLogLevel(LogLevel.Warn);
|
||||
Log.i("Log level: warn");
|
||||
}
|
||||
}
|
||||
Log.i("Logger is initialized");
|
||||
}
|
||||
|
||||
/// call this when all resources are supposed to be freed to report counts of non-freed resources by type
|
||||
extern (C) void releaseResourcesOnAppExit() {
|
||||
|
||||
//
|
||||
debug setAppShuttingDownFlag();
|
||||
|
||||
debug {
|
||||
if (Widget.instanceCount() > 0) {
|
||||
Log.e("Non-zero Widget instance count when exiting: ", Widget.instanceCount);
|
||||
}
|
||||
}
|
||||
|
||||
currentTheme = null;
|
||||
drawableCache = null;
|
||||
imageCache = null;
|
||||
FontManager.instance = null;
|
||||
|
||||
debug {
|
||||
if (DrawBuf.instanceCount > 0) {
|
||||
Log.e("Non-zero DrawBuf instance count when exiting: ", DrawBuf.instanceCount);
|
||||
}
|
||||
if (Style.instanceCount > 0) {
|
||||
Log.e("Non-zero Style instance count when exiting: ", Style.instanceCount);
|
||||
}
|
||||
if (ImageDrawable.instanceCount > 0) {
|
||||
Log.e("Non-zero ImageDrawable instance count when exiting: ", ImageDrawable.instanceCount);
|
||||
}
|
||||
if (Drawable.instanceCount > 0) {
|
||||
Log.e("Non-zero Drawable instance count when exiting: ", Drawable.instanceCount);
|
||||
}
|
||||
version (USE_FREETYPE) {
|
||||
import dlangui.graphics.ftfonts;
|
||||
if (FreeTypeFontFile.instanceCount > 0) {
|
||||
Log.e("Non-zero FreeTypeFontFile instance count when exiting: ", FreeTypeFontFile.instanceCount);
|
||||
}
|
||||
if (FreeTypeFont.instanceCount > 0) {
|
||||
Log.e("Non-zero FreeTypeFont instance count when exiting: ", FreeTypeFont.instanceCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -175,7 +175,8 @@ class SDLWindow : Window {
|
|||
version(USE_OPENGL) {
|
||||
if (_enableOpengl) {
|
||||
Log.i("Trying to create OpenGL 3.2 context");
|
||||
_context = SDL_GL_CreateContext(_win); // Create the actual context and make it current
|
||||
createContext(3, 2);
|
||||
//_context = SDL_GL_CreateContext(_win); // Create the actual context and make it current
|
||||
if (!_context) {
|
||||
Log.e("SDL_GL_CreateContext failed: ", fromStringz(SDL_GetError()));
|
||||
Log.w("trying other versions of OpenGL");
|
||||
|
@ -190,11 +191,17 @@ class SDLWindow : Window {
|
|||
}
|
||||
}
|
||||
if (_context && !_gl3Reloaded) {
|
||||
DerelictGL3.reload();
|
||||
_gl3Reloaded = true;
|
||||
if (!glSupport.valid && !glSupport.initShaders())
|
||||
_enableOpengl = false;
|
||||
fixSize();
|
||||
try {
|
||||
DerelictGL3.missingSymbolCallback = &gl3MissingSymFunc;
|
||||
DerelictGL3.reload(GLVersion.GL21, GLVersion.GL40);
|
||||
_gl3Reloaded = true;
|
||||
if (!glSupport.valid && !glSupport.initShaders())
|
||||
_enableOpengl = false;
|
||||
fixSize();
|
||||
} catch (derelict.util.exception.SymbolLoadException e) {
|
||||
Log.e("Exception in DerelictGL3.reload ", e);
|
||||
_enableOpengl = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1074,7 +1081,7 @@ class SDLPlatform : Platform {
|
|||
case SDL_KEYDOWN:
|
||||
SDLWindow w = getWindow(event.key.windowID);
|
||||
if (w) {
|
||||
w.processKeyEvent(KeyAction.KeyDown, event.key.keysym.sym, event.key.keysym.mod);
|
||||
w.processKeyEvent(KeyAction.KeyDown, event.key.keysym.sym, event.key.keysym.mod);
|
||||
SDL_StartTextInput();
|
||||
}
|
||||
break;
|
||||
|
@ -1177,9 +1184,6 @@ class SDLPlatform : Platform {
|
|||
protected SDLWindow[uint] _windowMap;
|
||||
}
|
||||
|
||||
// entry point
|
||||
extern(C) int UIAppMain(string[] args);
|
||||
|
||||
version (Windows) {
|
||||
import win32.windows;
|
||||
import dlangui.platforms.windows.win32fonts;
|
||||
|
@ -1266,9 +1270,6 @@ version (Windows) {
|
|||
|
||||
extern(C) int DLANGUImain(string[] args)
|
||||
{
|
||||
|
||||
initLogs();
|
||||
|
||||
return sdlmain(args);
|
||||
}
|
||||
}
|
||||
|
@ -1301,6 +1302,7 @@ int sdlmain(string[] args) {
|
|||
|
||||
version(USE_OPENGL) {
|
||||
try {
|
||||
DerelictGL3.missingSymbolCallback = &gl3MissingSymFunc;
|
||||
DerelictGL3.load();
|
||||
_enableOpengl = true;
|
||||
} catch (Exception e) {
|
||||
|
@ -1309,7 +1311,7 @@ int sdlmain(string[] args) {
|
|||
}
|
||||
|
||||
SDL_DisplayMode displayMode;
|
||||
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_EVENTS) != 0) {
|
||||
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_EVENTS|SDL_INIT_NOPARACHUTE) != 0) {
|
||||
Log.e("Cannot init SDL2");
|
||||
return 2;
|
||||
}
|
||||
|
@ -1336,7 +1338,8 @@ int sdlmain(string[] args) {
|
|||
if (!sdl.connect()) {
|
||||
return 1;
|
||||
}
|
||||
Platform.setInstance(sdl);
|
||||
|
||||
Platform.setInstance(sdl);
|
||||
|
||||
int res = 0;
|
||||
|
||||
|
|
|
@ -0,0 +1,252 @@
|
|||
module dlangui.platforms.x11.x11app;
|
||||
|
||||
version (USE_X11):
|
||||
|
||||
import dlangui.core.logger;
|
||||
import dlangui.core.events;
|
||||
import dlangui.core.files;
|
||||
import dlangui.graphics.drawbuf;
|
||||
import dlangui.graphics.fonts;
|
||||
import dlangui.graphics.ftfonts;
|
||||
import dlangui.graphics.resources;
|
||||
import dlangui.widgets.styles;
|
||||
import dlangui.widgets.widget;
|
||||
import dlangui.platforms.common.platform;
|
||||
|
||||
import x11.Xlib;
|
||||
import x11.Xutil;
|
||||
import x11.Xtos;
|
||||
import x11.X;
|
||||
|
||||
pragma(lib, "X11");
|
||||
|
||||
private __gshared Display * x11display;
|
||||
private __gshared int x11screen;
|
||||
|
||||
class X11Window : dlangui.platforms.common.platform.Window {
|
||||
protected X11Platform _platform;
|
||||
protected dstring _caption;
|
||||
protected x11.Xlib.Window _win;
|
||||
protected GC _gc;
|
||||
|
||||
this(X11Platform platform, dstring caption, dlangui.platforms.common.platform.Window parent, uint flags, uint width = 0, uint height = 0) {
|
||||
_platform = platform;
|
||||
_caption = caption;
|
||||
debug Log.d("Creating SDL window");
|
||||
_dx = width;
|
||||
_dy = height;
|
||||
//create(flags);
|
||||
|
||||
/* get the colors black and white (see section for details) */
|
||||
ulong black, white;
|
||||
black = BlackPixel(x11display, x11screen); /* get color black */
|
||||
white = WhitePixel(x11display, x11screen); /* get color white */
|
||||
|
||||
/* once the display is initialized, create the window.
|
||||
This window will be have be 200 pixels across and 300 down.
|
||||
It will have the foreground white and background black
|
||||
*/
|
||||
_win = XCreateSimpleWindow(x11display, DefaultRootWindow(x11display), 0, 0,
|
||||
_dx, _dy, 5, white, black);
|
||||
|
||||
/* here is where some properties of the window can be set.
|
||||
The third and fourth items indicate the name which appears
|
||||
at the top of the window and the name of the minimized window
|
||||
respectively.
|
||||
*/
|
||||
XSetStandardProperties(x11display, _win, cast(char*)"My Window".ptr, cast(char*)"HI!".ptr, None, cast(char**)null, 0, cast(XSizeHints*)null);
|
||||
|
||||
/* this routine determines which types of input are allowed in
|
||||
the input. see the appropriate section for details...
|
||||
*/
|
||||
XSelectInput(x11display, _win, ExposureMask|ButtonPressMask|KeyPressMask);
|
||||
|
||||
/* create the Graphics Context */
|
||||
_gc = XCreateGC(x11display, _win, 0, cast(XGCValues*)null);
|
||||
|
||||
/* here is another routine to set the foreground and background
|
||||
colors _currently_ in use in the window.
|
||||
*/
|
||||
XSetBackground(x11display, _gc, white);
|
||||
XSetForeground(x11display, _gc, black);
|
||||
|
||||
/* clear the window and bring it on top of the other windows */
|
||||
XClearWindow(x11display, _win);
|
||||
}
|
||||
|
||||
~this() {
|
||||
if (_gc)
|
||||
XFreeGC(x11display, _gc);
|
||||
if (_win)
|
||||
XDestroyWindow(x11display, _win);
|
||||
}
|
||||
|
||||
/// show window
|
||||
override void show() {
|
||||
XMapRaised(x11display, _win);
|
||||
}
|
||||
|
||||
override @property dstring windowCaption() {
|
||||
return _caption;
|
||||
}
|
||||
|
||||
override @property void windowCaption(dstring caption) {
|
||||
_caption = caption;
|
||||
//if (_win)
|
||||
// SDL_SetWindowTitle(_win, toUTF8(_caption).toStringz);
|
||||
}
|
||||
|
||||
/// sets window icon
|
||||
override @property void windowIcon(DrawBufRef icon) {
|
||||
}
|
||||
/// request window redraw
|
||||
override void invalidate() {
|
||||
}
|
||||
|
||||
/// close window
|
||||
override void close() {
|
||||
}
|
||||
}
|
||||
|
||||
class X11Platform : Platform {
|
||||
|
||||
this() {
|
||||
}
|
||||
|
||||
/**
|
||||
* create window
|
||||
* Args:
|
||||
* windowCaption = window caption text
|
||||
* parent = parent Window, or null if no parent
|
||||
* flags = WindowFlag bit set, combination of Resizable, Modal, Fullscreen
|
||||
* width = window width
|
||||
* height = window height
|
||||
*
|
||||
* Window w/o Resizable nor Fullscreen will be created with size based on measurement of its content widget
|
||||
*/
|
||||
override dlangui.platforms.common.platform.Window createWindow(dstring windowCaption, dlangui.platforms.common.platform.Window parent, uint flags = WindowFlag.Resizable, uint width = 0, uint height = 0) {
|
||||
int newwidth = width;
|
||||
int newheight = height;
|
||||
X11Window window = new X11Window(this, windowCaption, parent, flags, newwidth, newheight);
|
||||
return window;
|
||||
}
|
||||
|
||||
/**
|
||||
* close window
|
||||
*
|
||||
* Closes window earlier created with createWindow()
|
||||
*/
|
||||
override void closeWindow(dlangui.platforms.common.platform.Window w) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts application message loop.
|
||||
*
|
||||
* When returned from this method, application is shutting down.
|
||||
*/
|
||||
override int enterMessageLoop() {
|
||||
XEvent event; /* the XEvent declaration !!! */
|
||||
KeySym key; /* a dealie-bob to handle KeyPress Events */
|
||||
char[255] text; /* a char buffer for KeyPress Events */
|
||||
|
||||
/* look for events forever... */
|
||||
while(1) {
|
||||
/* get the next event and stuff it into our event variable.
|
||||
Note: only events we set the mask for are detected!
|
||||
*/
|
||||
XNextEvent(x11display, &event);
|
||||
|
||||
if (event.type==Expose && event.xexpose.count==0) {
|
||||
/* the window was exposed redraw it! */
|
||||
//redraw();
|
||||
}
|
||||
if (event.type == KeyPress &&
|
||||
XLookupString(&event.xkey, text.ptr, 255, &key, cast(XComposeStatus*)null) == 1) {
|
||||
/* use the XLookupString routine to convert the invent
|
||||
KeyPress data into regular text. Weird but necessary...
|
||||
*/
|
||||
if (text[0]=='q') {
|
||||
break;
|
||||
//close_x();
|
||||
}
|
||||
Log.d("You pressed the key", text[0]);
|
||||
}
|
||||
if (event.type==ButtonPress) {
|
||||
/* tell where the mouse Button was Pressed */
|
||||
Log.d("You pressed a button at ",
|
||||
event.xbutton.x, ", ", event.xbutton.y);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// retrieves text from clipboard (when mouseBuffer == true, use mouse selection clipboard - under linux)
|
||||
override dstring getClipboardText(bool mouseBuffer = false) {
|
||||
return "";
|
||||
}
|
||||
|
||||
/// sets text to clipboard (when mouseBuffer == true, use mouse selection clipboard - under linux)
|
||||
override void setClipboardText(dstring text, bool mouseBuffer = false) {
|
||||
// todo
|
||||
}
|
||||
|
||||
/// calls request layout for all windows
|
||||
override void requestLayout() {
|
||||
// todo
|
||||
}
|
||||
}
|
||||
|
||||
extern(C) int DLANGUImain(string[] args)
|
||||
{
|
||||
initLogs();
|
||||
|
||||
if (!initFontManager()) {
|
||||
Log.e("******************************************************************");
|
||||
Log.e("No font files found!!!");
|
||||
Log.e("Currently, only hardcoded font paths implemented.");
|
||||
Log.e("Probably you can modify sdlapp.d to add some fonts for your system.");
|
||||
Log.e("TODO: use fontconfig");
|
||||
Log.e("******************************************************************");
|
||||
assert(false);
|
||||
}
|
||||
|
||||
|
||||
/* use the information from the environment variable DISPLAY
|
||||
to create the X connection:
|
||||
*/
|
||||
x11display = XOpenDisplay(null);
|
||||
if (!x11display) {
|
||||
Log.e("Cannot open X11 display");
|
||||
return 1;
|
||||
}
|
||||
|
||||
x11screen = DefaultScreen(x11display);
|
||||
|
||||
|
||||
currentTheme = createDefaultTheme();
|
||||
|
||||
X11Platform x11platform = new X11Platform();
|
||||
|
||||
Platform.setInstance(x11platform);
|
||||
|
||||
int res = 0;
|
||||
|
||||
version (unittest) {
|
||||
} else {
|
||||
res = UIAppMain(args);
|
||||
}
|
||||
|
||||
//Log.e("Widget instance count after UIAppMain: ", Widget.instanceCount());
|
||||
|
||||
Log.d("Destroying X11 platform");
|
||||
Platform.setInstance(null);
|
||||
|
||||
releaseResourcesOnAppExit();
|
||||
|
||||
|
||||
XCloseDisplay(x11display);
|
||||
|
||||
Log.d("Exiting main width result=", res);
|
||||
|
||||
return res;
|
||||
}
|
|
@ -54,4 +54,19 @@ class SourceEdit : EditBox {
|
|||
_filename = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool save(string fn) {
|
||||
if (content.save(fn)) {
|
||||
_filename = fn;
|
||||
requestLayout();
|
||||
window.update();
|
||||
return true;
|
||||
}
|
||||
// failed
|
||||
requestLayout();
|
||||
window.update();
|
||||
_filename = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -827,8 +827,8 @@ class Theme : Style {
|
|||
_fontSize = 9 | SIZE_IN_POINTS_FLAG; // TODO: from settings or screen properties / DPI
|
||||
_fontStyle = FONT_STYLE_NORMAL;
|
||||
_fontWeight = 400;
|
||||
//_fontFace = "Arial"; // TODO: from settings
|
||||
_fontFace = "Verdana"; // TODO: from settings
|
||||
_fontFace = "Arial"; // TODO: from settings
|
||||
//_fontFace = "Verdana"; // TODO: from settings
|
||||
_fontFamily = FontFamily.SansSerif;
|
||||
_minHeight = 0;
|
||||
_minWidth = 0;
|
||||
|
|
|
@ -1579,7 +1579,7 @@ class Widget {
|
|||
alpha = cast(ushort)value;
|
||||
return true;
|
||||
}
|
||||
mixin(generatePropertySetters("minWidth", "maxWidth", "minHeight", "maxHeight", "layoutWidth", "layoutHeight", "textColor", "backgroundColor", "fontSize", "fontWeight"));
|
||||
mixin(generatePropertySetters("minWidth", "maxWidth", "minHeight", "maxHeight", "layoutWidth", "layoutHeight", "layoutWeight", "textColor", "backgroundColor", "fontSize", "fontWeight"));
|
||||
if (name.equal("margins")) { // use same value for all sides
|
||||
margins = Rect(value, value, value, value);
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue