mirror of https://github.com/buggins/dlangui.git
ML parser improvements; allow specifying percent size for layoutWidth, layoutHeight in percents
This commit is contained in:
parent
2877cba890
commit
f0a615ed82
|
@ -34,6 +34,9 @@ EndProject
|
||||||
Project("{002A2DE9-8BB6-484D-9802-7E4AD4084715}") = "dsfml", "..\DSFML\dsfml\dsfml.visualdproj", "{DB490C05-D9F8-431C-91DD-CEE646A64FDA}"
|
Project("{002A2DE9-8BB6-484D-9802-7E4AD4084715}") = "dsfml", "..\DSFML\dsfml\dsfml.visualdproj", "{DB490C05-D9F8-431C-91DD-CEE646A64FDA}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{002A2DE9-8BB6-484D-9802-7E4AD4084715}") = "dmledit", "examples\dmledit\dmledit.visualdproj", "{06D73450-2919-48A8-B2C3-738B12505D74}"
|
Project("{002A2DE9-8BB6-484D-9802-7E4AD4084715}") = "dmledit", "examples\dmledit\dmledit.visualdproj", "{06D73450-2919-48A8-B2C3-738B12505D74}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{5FF17402-9997-4D0E-8068-6D84B8769D98} = {5FF17402-9997-4D0E-8068-6D84B8769D98}
|
||||||
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
|
|
@ -4,13 +4,131 @@ import dlangui;
|
||||||
|
|
||||||
mixin APP_ENTRY_POINT;
|
mixin APP_ENTRY_POINT;
|
||||||
|
|
||||||
|
// action codes
|
||||||
|
enum IDEActions : int {
|
||||||
|
//ProjectOpen = 1010000,
|
||||||
|
FileNew = 1010000,
|
||||||
|
FileOpen,
|
||||||
|
FileSave,
|
||||||
|
FileSaveAs,
|
||||||
|
FileSaveAll,
|
||||||
|
FileClose,
|
||||||
|
FileExit,
|
||||||
|
EditPreferences,
|
||||||
|
}
|
||||||
|
|
||||||
|
// actions
|
||||||
|
const Action ACTION_FILE_NEW = new Action(IDEActions.FileNew, "MENU_FILE_NEW"c, "document-new", KeyCode.KEY_N, KeyFlag.Control);
|
||||||
|
const Action ACTION_FILE_SAVE = (new Action(IDEActions.FileSave, "MENU_FILE_SAVE"c, "document-save", KeyCode.KEY_S, KeyFlag.Control)).disableByDefault();
|
||||||
|
const Action ACTION_FILE_SAVE_AS = (new Action(IDEActions.FileSaveAs, "MENU_FILE_SAVE_AS"c)).disableByDefault();
|
||||||
|
const Action ACTION_FILE_OPEN = new Action(IDEActions.FileOpen, "MENU_FILE_OPEN"c, "document-open", KeyCode.KEY_O, KeyFlag.Control);
|
||||||
|
const Action ACTION_FILE_EXIT = new Action(IDEActions.FileExit, "MENU_FILE_EXIT"c, "document-close"c, KeyCode.KEY_X, KeyFlag.Alt);
|
||||||
|
const Action ACTION_EDIT_COPY = (new Action(EditorActions.Copy, "MENU_EDIT_COPY"c, "edit-copy"c, KeyCode.KEY_C, KeyFlag.Control)).addAccelerator(KeyCode.INS, KeyFlag.Control).disableByDefault();
|
||||||
|
const Action ACTION_EDIT_PASTE = (new Action(EditorActions.Paste, "MENU_EDIT_PASTE"c, "edit-paste"c, KeyCode.KEY_V, KeyFlag.Control)).addAccelerator(KeyCode.INS, KeyFlag.Shift).disableByDefault();
|
||||||
|
const Action ACTION_EDIT_CUT = (new Action(EditorActions.Cut, "MENU_EDIT_CUT"c, "edit-cut"c, KeyCode.KEY_X, KeyFlag.Control)).addAccelerator(KeyCode.DEL, KeyFlag.Shift).disableByDefault();
|
||||||
|
const Action ACTION_EDIT_UNDO = (new Action(EditorActions.Undo, "MENU_EDIT_UNDO"c, "edit-undo"c, KeyCode.KEY_Z, KeyFlag.Control)).disableByDefault();
|
||||||
|
const Action ACTION_EDIT_REDO = (new Action(EditorActions.Redo, "MENU_EDIT_REDO"c, "edit-redo"c, KeyCode.KEY_Y, KeyFlag.Control)).addAccelerator(KeyCode.KEY_Z, KeyFlag.Control|KeyFlag.Shift).disableByDefault();
|
||||||
|
const Action ACTION_EDIT_INDENT = (new Action(EditorActions.Indent, "MENU_EDIT_INDENT"c, "edit-indent"c, KeyCode.TAB, 0)).addAccelerator(KeyCode.KEY_BRACKETCLOSE, KeyFlag.Control).disableByDefault();
|
||||||
|
const Action ACTION_EDIT_UNINDENT = (new Action(EditorActions.Unindent, "MENU_EDIT_UNINDENT"c, "edit-unindent", KeyCode.TAB, KeyFlag.Shift)).addAccelerator(KeyCode.KEY_BRACKETOPEN, KeyFlag.Control).disableByDefault();
|
||||||
|
const Action ACTION_EDIT_TOGGLE_LINE_COMMENT = (new Action(EditorActions.ToggleLineComment, "MENU_EDIT_TOGGLE_LINE_COMMENT"c, null, KeyCode.KEY_DIVIDE, KeyFlag.Control)).disableByDefault();
|
||||||
|
const Action ACTION_EDIT_TOGGLE_BLOCK_COMMENT = (new Action(EditorActions.ToggleBlockComment, "MENU_EDIT_TOGGLE_BLOCK_COMMENT"c, null, KeyCode.KEY_DIVIDE, KeyFlag.Control|KeyFlag.Shift)).disableByDefault();
|
||||||
|
const Action ACTION_EDIT_PREFERENCES = (new Action(IDEActions.EditPreferences, "MENU_EDIT_PREFERENCES"c, null)).disableByDefault();
|
||||||
|
|
||||||
|
class EditFrame : AppFrame {
|
||||||
|
|
||||||
|
MenuItem mainMenuItems;
|
||||||
|
|
||||||
|
override protected void init() {
|
||||||
|
_appName = "DMLEdit";
|
||||||
|
super.init();
|
||||||
|
}
|
||||||
|
/// create main menu
|
||||||
|
override protected MainMenu createMainMenu() {
|
||||||
|
return new MainMenu(new MenuItem());
|
||||||
|
mainMenuItems = new MenuItem();
|
||||||
|
MenuItem fileItem = new MenuItem(new Action(1, "MENU_FILE"));
|
||||||
|
fileItem.add(ACTION_FILE_NEW, ACTION_FILE_OPEN,
|
||||||
|
ACTION_FILE_EXIT);
|
||||||
|
|
||||||
|
MenuItem editItem = new MenuItem(new Action(2, "MENU_EDIT"));
|
||||||
|
editItem.add(ACTION_EDIT_COPY, ACTION_EDIT_PASTE,
|
||||||
|
ACTION_EDIT_CUT, ACTION_EDIT_UNDO, ACTION_EDIT_REDO,
|
||||||
|
ACTION_EDIT_INDENT, ACTION_EDIT_UNINDENT, ACTION_EDIT_TOGGLE_LINE_COMMENT, ACTION_EDIT_TOGGLE_BLOCK_COMMENT);
|
||||||
|
|
||||||
|
editItem.add(ACTION_EDIT_PREFERENCES);
|
||||||
|
|
||||||
|
MainMenu mainMenu = new MainMenu(mainMenuItems);
|
||||||
|
return mainMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// create app toolbars
|
||||||
|
override protected ToolBarHost createToolbars() {
|
||||||
|
ToolBarHost res = new ToolBarHost();
|
||||||
|
ToolBar tb;
|
||||||
|
tb = res.getOrAddToolbar("Standard");
|
||||||
|
tb.addButtons(ACTION_FILE_NEW, ACTION_FILE_OPEN, ACTION_FILE_SAVE);
|
||||||
|
|
||||||
|
tb = res.getOrAddToolbar("Edit");
|
||||||
|
tb.addButtons(ACTION_EDIT_COPY, ACTION_EDIT_PASTE, ACTION_EDIT_CUT, ACTION_SEPARATOR,
|
||||||
|
ACTION_EDIT_UNDO, ACTION_EDIT_REDO, ACTION_EDIT_INDENT, ACTION_EDIT_UNINDENT);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// create app body widget
|
||||||
|
override protected Widget createBody() {
|
||||||
|
VerticalLayout bodyWidget = new VerticalLayout();
|
||||||
|
bodyWidget.layoutWidth = FILL_PARENT;
|
||||||
|
bodyWidget.layoutHeight = FILL_PARENT;
|
||||||
|
HorizontalLayout hlayout = new HorizontalLayout();
|
||||||
|
hlayout.layoutWidth = makePercentSize(50);
|
||||||
|
hlayout.layoutHeight = FILL_PARENT;
|
||||||
|
SourceEdit editor = new SourceEdit();
|
||||||
|
hlayout.addChild(editor);
|
||||||
|
ScrollWidget preview = new ScrollWidget();
|
||||||
|
preview.layoutWidth = FILL_PARENT;
|
||||||
|
preview.layoutHeight = FILL_PARENT;
|
||||||
|
hlayout.addChild(preview);
|
||||||
|
bodyWidget.addChild(hlayout);
|
||||||
|
return bodyWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// entry point for dlangui based application
|
/// entry point for dlangui based application
|
||||||
extern (C) int UIAppMain(string[] args) {
|
extern (C) int UIAppMain(string[] args) {
|
||||||
|
|
||||||
|
// embed non-standard resources listed in views/resources.list into executable
|
||||||
|
embeddedResourceList.addResources(embedResourcesFromList!("resources.list")());
|
||||||
|
|
||||||
// create window
|
// create window
|
||||||
Window window = Platform.instance.createWindow("DlangUI example - HelloWorld", null);
|
Window window = Platform.instance.createWindow("DlangUI ML editor"d, null, WindowFlag.Resizable, 700, 470);
|
||||||
|
|
||||||
// create some widget to show in window
|
// create some widget to show in window
|
||||||
window.mainWidget = (new Button()).text("Hello, world!"d).margins(Rect(20,20,20,20));
|
window.windowIcon = drawableCache.getImage("dlangui-logo1");
|
||||||
|
|
||||||
|
|
||||||
|
// create some widget to show in window
|
||||||
|
window.mainWidget = new EditFrame();
|
||||||
|
/*
|
||||||
|
parseML(q{
|
||||||
|
VerticalLayout {
|
||||||
|
id: vlayout
|
||||||
|
margins: Rect { left: 5; right: 3; top: 2; bottom: 4 }
|
||||||
|
padding: Rect { 5, 4, 3, 2 } // same as Rect { left: 5; top: 4; right: 3; bottom: 2 }
|
||||||
|
TextWidget {
|
||||||
|
id: myLabel1
|
||||||
|
text: "Some text"; padding: 5
|
||||||
|
enabled: false
|
||||||
|
}
|
||||||
|
TextWidget {
|
||||||
|
id: myLabel2
|
||||||
|
text: SOME_TEXT_RESOURCE_ID; margins: 5
|
||||||
|
enabled: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
// show window
|
// show window
|
||||||
window.show();
|
window.show();
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 516 B |
|
@ -2,6 +2,7 @@ res/i18n/en.ini
|
||||||
res/i18n/ru.ini
|
res/i18n/ru.ini
|
||||||
res/mdpi/cr3_logo.png
|
res/mdpi/cr3_logo.png
|
||||||
res/mdpi/document-close.png
|
res/mdpi/document-close.png
|
||||||
|
res/mdpi/document-new.png
|
||||||
res/mdpi/document-open-recent.png
|
res/mdpi/document-open-recent.png
|
||||||
res/mdpi/document-open.png
|
res/mdpi/document-open.png
|
||||||
res/mdpi/document-properties.png
|
res/mdpi/document-properties.png
|
||||||
|
|
|
@ -1,3 +1,18 @@
|
||||||
|
// Written in the D programming language.
|
||||||
|
|
||||||
|
/**
|
||||||
|
This module is DML (DlangUI Markup Language) parser - similar to QML in QtQuick
|
||||||
|
|
||||||
|
Synopsis:
|
||||||
|
|
||||||
|
----
|
||||||
|
// helloworld
|
||||||
|
----
|
||||||
|
|
||||||
|
Copyright: Vadim Lopatin, 2015
|
||||||
|
License: Boost License 1.0
|
||||||
|
Authors: Vadim Lopatin, coolreader.org@gmail.com
|
||||||
|
*/
|
||||||
module dlangui.core.parser;
|
module dlangui.core.parser;
|
||||||
|
|
||||||
import dlangui.core.linestream;
|
import dlangui.core.linestream;
|
||||||
|
@ -21,7 +36,7 @@ class ParserException : Exception {
|
||||||
@property int pos() { return _pos; }
|
@property int pos() { return _pos; }
|
||||||
|
|
||||||
this(string msg, string file, int line, int pos) {
|
this(string msg, string file, int line, int pos) {
|
||||||
super(msg ~ " at " ~ _file ~ " line " ~ to!string(line) ~ " column " ~ to!string(pos));
|
super(msg ~ " at " ~ file ~ " line " ~ to!string(line) ~ " column " ~ to!string(pos));
|
||||||
_msg = msg;
|
_msg = msg;
|
||||||
_file = file;
|
_file = file;
|
||||||
_line = line;
|
_line = line;
|
||||||
|
@ -29,6 +44,28 @@ class ParserException : Exception {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// parser exception - unknown (unregistered) widget name
|
||||||
|
class UnknownWidgetException : ParserException {
|
||||||
|
protected string _objectName;
|
||||||
|
|
||||||
|
@property string objectName() { return _objectName; }
|
||||||
|
|
||||||
|
this(string msg, string objectName, string file, int line, int pos) {
|
||||||
|
super(msg is null ? "Unknown widget name: " ~ objectName : msg, file, line, pos);
|
||||||
|
_objectName = objectName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// parser exception - unknown property for widget
|
||||||
|
class UnknownPropertyException : UnknownWidgetException {
|
||||||
|
protected string _propName;
|
||||||
|
|
||||||
|
@property string propName() { return _propName; }
|
||||||
|
|
||||||
|
this(string msg, string objectName, string propName, string file, int line, int pos) {
|
||||||
|
super(msg is null ? "Unknown property " ~ objectName ~ "." ~ propName : msg, objectName, file, line, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum TokenType : ushort {
|
enum TokenType : ushort {
|
||||||
/// end of file
|
/// end of file
|
||||||
|
@ -406,6 +443,14 @@ class Tokenizer {
|
||||||
throw new ParserException(msg ~ getContextSource(), _filename, _token.line, _token.pos);
|
throw new ParserException(msg ~ getContextSource(), _filename, _token.line, _token.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void emitUnknownPropertyError(string objectName, string propName) {
|
||||||
|
throw new UnknownPropertyException("Unknown property " ~ objectName ~ "." ~ propName ~ getContextSource(), objectName, propName, _filename, _token.line, _token.pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void emitUnknownObjectError(string objectName) {
|
||||||
|
throw new UnknownWidgetException("Unknown widget type " ~ objectName ~ getContextSource(), objectName, _filename, _token.line, _token.pos);
|
||||||
|
}
|
||||||
|
|
||||||
void emitError(string msg, ref const Token token) {
|
void emitError(string msg, ref const Token token) {
|
||||||
throw new ParserException(msg, _filename, token.line, token.pos);
|
throw new ParserException(msg, _filename, token.line, token.pos);
|
||||||
}
|
}
|
||||||
|
@ -481,6 +526,14 @@ class MLParser {
|
||||||
_tokenizer.emitError(msg);
|
_tokenizer.emitError(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void unknownObjectError(string objectName) {
|
||||||
|
_tokenizer.emitUnknownObjectError(objectName);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void unknownPropertyError(string objectName, string propName) {
|
||||||
|
_tokenizer.emitUnknownPropertyError(objectName, propName);
|
||||||
|
}
|
||||||
|
|
||||||
Widget createWidget(string name) {
|
Widget createWidget(string name) {
|
||||||
auto metadata = findWidgetMetadata(name);
|
auto metadata = findWidgetMetadata(name);
|
||||||
if (!metadata)
|
if (!metadata)
|
||||||
|
|
|
@ -215,6 +215,29 @@ int makePercentSize(int percent) {
|
||||||
return (percent * 100) | SIZE_IN_PERCENTS_FLAG;
|
return (percent * 100) | SIZE_IN_PERCENTS_FLAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// make size value with SIZE_IN_PERCENTS_FLAG set
|
||||||
|
int makePercentSize(double percent) {
|
||||||
|
return cast(int)(percent * 100) | SIZE_IN_PERCENTS_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns true for WRAP_CONTENT, WRAP_CONTENT, SIZE_UNSPECIFIED
|
||||||
|
bool isSpecialSize(int sz) {
|
||||||
|
// don't forget to update if more special constants added
|
||||||
|
return (sz & (WRAP_CONTENT | FILL_PARENT | SIZE_UNSPECIFIED)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns true if size has SIZE_IN_PERCENTS_FLAG bit set
|
||||||
|
bool isPercentSize(int size) {
|
||||||
|
return (size & SIZE_IN_PERCENTS_FLAG) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// if size has SIZE_IN_PERCENTS_FLAG bit set, returns percent of baseSize, otherwise returns size unchanged
|
||||||
|
int fromPercentSize(int size, int baseSize) {
|
||||||
|
if (isPercentSize(size))
|
||||||
|
return cast(int)(cast(long)(size & ~SIZE_IN_PERCENTS_FLAG) * baseSize / 10000);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
/// screen dots per inch
|
/// screen dots per inch
|
||||||
private __gshared int PRIVATE_SCREEN_DPI = 96;
|
private __gshared int PRIVATE_SCREEN_DPI = 96;
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,7 @@ public import dlangui.widgets.popup;
|
||||||
public import dlangui.widgets.appframe;
|
public import dlangui.widgets.appframe;
|
||||||
public import dlangui.widgets.statusline;
|
public import dlangui.widgets.statusline;
|
||||||
public import dlangui.widgets.docks;
|
public import dlangui.widgets.docks;
|
||||||
|
public import dlangui.widgets.toolbars;
|
||||||
public import dlangui.platforms.common.platform;
|
public import dlangui.platforms.common.platform;
|
||||||
public import dlangui.core.parser;
|
public import dlangui.core.parser;
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,13 @@ class AppFrame : VerticalLayout, MenuItemClickHandler, MenuItemActionHandler {
|
||||||
protected ulong _currentBackgroundOperationTimer;
|
protected ulong _currentBackgroundOperationTimer;
|
||||||
|
|
||||||
|
|
||||||
|
this() {
|
||||||
|
super("APP_FRAME");
|
||||||
|
layoutWidth = FILL_PARENT;
|
||||||
|
layoutHeight = FILL_PARENT;
|
||||||
|
_appName = "dlangui";
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
protected string _appName;
|
protected string _appName;
|
||||||
/// override to return some identifier for app, e.g. to use as settings directory name
|
/// override to return some identifier for app, e.g. to use as settings directory name
|
||||||
|
@ -210,14 +217,6 @@ class AppFrame : VerticalLayout, MenuItemClickHandler, MenuItemActionHandler {
|
||||||
/// body widget
|
/// body widget
|
||||||
@property Widget frameBody() { return _body; }
|
@property Widget frameBody() { return _body; }
|
||||||
|
|
||||||
this() {
|
|
||||||
super("APP_FRAME");
|
|
||||||
layoutWidth = FILL_PARENT;
|
|
||||||
layoutHeight = FILL_PARENT;
|
|
||||||
_appName = "dlangui";
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// map key to action
|
/// map key to action
|
||||||
override Action findKeyAction(uint keyCode, uint flags) {
|
override Action findKeyAction(uint keyCode, uint flags) {
|
||||||
if (_mainMenu) {
|
if (_mainMenu) {
|
||||||
|
|
|
@ -205,12 +205,6 @@ immutable uint TEXT_FLAGS_USE_PARENT = uint.max - 1;
|
||||||
/// to take layout weight from parent
|
/// to take layout weight from parent
|
||||||
immutable int WEIGHT_UNSPECIFIED = -1;
|
immutable int WEIGHT_UNSPECIFIED = -1;
|
||||||
|
|
||||||
/// returns true for WRAP_CONTENT, WRAP_CONTENT, SIZE_UNSPECIFIED
|
|
||||||
bool isSpecialSize(int sz) {
|
|
||||||
// don't forget to update if more special constants added
|
|
||||||
return sz >= WRAP_CONTENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Align option bit constants
|
/// Align option bit constants
|
||||||
enum Align : ubyte {
|
enum Align : ubyte {
|
||||||
/// alignment is not specified
|
/// alignment is not specified
|
||||||
|
|
|
@ -1223,9 +1223,13 @@ class Widget {
|
||||||
// check for fixed size set in layoutWidth, layoutHeight
|
// check for fixed size set in layoutWidth, layoutHeight
|
||||||
int lh = layoutHeight;
|
int lh = layoutHeight;
|
||||||
int lw = layoutWidth;
|
int lw = layoutWidth;
|
||||||
if (!isSpecialSize(lh))
|
if (isPercentSize(lh) && parentHeight != SIZE_UNSPECIFIED)
|
||||||
|
dy = fromPercentSize(lh, parentHeight);
|
||||||
|
else if (!isSpecialSize(lh))
|
||||||
dy = lh;
|
dy = lh;
|
||||||
if (!isSpecialSize(lw))
|
if (isPercentSize(lw) && parentWidth != SIZE_UNSPECIFIED)
|
||||||
|
dy = fromPercentSize(lw, parentWidth);
|
||||||
|
else if (!isSpecialSize(lw))
|
||||||
dx = lw;
|
dx = lw;
|
||||||
// apply min/max width and height constraints
|
// apply min/max width and height constraints
|
||||||
int minw = minWidth;
|
int minw = minWidth;
|
||||||
|
|
Loading…
Reference in New Issue