Many improvements.

This commit is contained in:
Vortrex
2020-12-04 02:48:16 -06:00
parent a7cc0bce7c
commit 33f8c4615a
110 changed files with 3680 additions and 923 deletions

View File

@@ -21,12 +21,15 @@ mexui.Component.Control.defaultStyles = mexui.util.linkStyles(mexui.Entity.Style
// input
mexui.Component.Control.prototype.onMouseDown = function(e)
{
var hit = this.isCursorOverControl();
if(hit)
if(e.button == 0)
{
e.used = true;
e.clickedAControl = true;
mexui.focusedControl = this;
var hit = this.isCursorOverControl();
if(hit)
{
e.used = true;
e.clickedAControl = true;
mexui.focusedControl = this;
}
}
};

View File

@@ -45,7 +45,7 @@ mexui.Component.Window.defaultStyles = mexui.util.linkStyles(mexui.Entity.Stylea
// input
mexui.Component.Window.prototype.onMouseDown = function(e)
{
if(this.titleBarShown && this.titleBarIconShown && this.isCursorOverCloseIcon())
if(e.button == 0 && this.titleBarShown && this.titleBarIconShown && this.isCursorOverCloseIcon())
{
this.shown = false;
mexui.setInput(false);
@@ -240,7 +240,14 @@ mexui.Component.Window.prototype.triggerEvent = function(eventName, e, data, cal
{
this.controls[i][eventName].call(control, e, data);
if(e.used)
{
if(e.button == 0 && eventName == 'onMouseDown')
{
mexui.focusedControl = this.controls[i];
e.clickedAControl = true;
}
break;
}
if(mexui.Entity.Component.prototype[eventName])
{
@@ -360,6 +367,8 @@ mexui.Component.Window.prototype.minute = function(x, y, w, h, text, styles, c
mexui.Component.Window.prototype.month = function(x, y, w, h, text, styles, callback) { return this.addControl(new mexui.Control.Month(this, x, y, w, h, text, styles, callback)); };
mexui.Component.Window.prototype.number = function(x, y, w, h, text, styles, callback) { return this.addControl(new mexui.Control.Number(this, x, y, w, h, text, styles, callback)); };
mexui.Component.Window.prototype.password = function(x, y, w, h, text, styles, callback) { return this.addControl(new mexui.Control.Password(this, x, y, w, h, text, styles, callback)); };
mexui.Component.Window.prototype.positiveInteger = function(x, y, w, h, text, styles, callback) { return this.addControl(new mexui.Control.PositiveInteger(this, x, y, w, h, text, styles, callback)); };
mexui.Component.Window.prototype.positiveNumber = function(x, y, w, h, text, styles, callback) { return this.addControl(new mexui.Control.PositiveNumber(this, x, y, w, h, text, styles, callback)); };
mexui.Component.Window.prototype.progressBar = function(x, y, w, h, text, styles) { return this.addControl(new mexui.Control.ProgressBar(this, x, y, w, h, text, styles)); };
mexui.Component.Window.prototype.radioButton = function(x, y, w, h, text, groupId, styles, callback) { return this.addControl(new mexui.Control.RadioButton(this, x, y, w, h, text, groupId, styles, callback)); };
mexui.Component.Window.prototype.rangedInteger = function(x, y, w, h, text, min, max, styles, callback) { return this.addControl(new mexui.Control.RangedInteger(this, x, y, w, h, text, min, max, styles, callback)); };
@@ -375,5 +384,6 @@ mexui.Component.Window.prototype.textInput = function(x, y, w, h, text, styles,
mexui.Component.Window.prototype.time = function(x, y, w, h, text, styles, callback) { return this.addControl(new mexui.Control.Time(this, x, y, w, h, text, styles, callback)); };
mexui.Component.Window.prototype.tree = function(x, y, w, h, styles, callback) { return this.addControl(new mexui.Control.Tree(this, x, y, w, h, styles, callback)); };
mexui.Component.Window.prototype.week = function(x, y, w, h, text, styles, callback) { return this.addControl(new mexui.Control.Week(this, x, y, w, h, text, styles, callback)); };
mexui.Component.Window.prototype.weekDay = function(x, y, w, h, text, styles, callback) { return this.addControl(new mexui.Control.WeekDay(this, x, y, w, h, text, styles, callback)); };
mexui.Component.Window.prototype.year = function(x, y, w, h, text, styles, callback) { return this.addControl(new mexui.Control.Year(this, x, y, w, h, text, styles, callback)); };

View File

@@ -11,7 +11,16 @@ mexui.util.linkBaseControlStyles('Button', {});
// input
mexui.Control.Button.prototype.onMouseDown = function(e)
{
if(this.isCursorOverControl())
if(e.button == 0 && this.isCursorOverControl())
{
e.used = true;
this.checkToCallCallback();
}
};
mexui.Control.Button.prototype.onKeyDown = function(e, key, mods)
{
if(this.isFocused() && (key == SDLK_RETURN || key == SDLK_RETURN2 || key == SDLK_KP_ENTER || key == SDLK_SPACE))
{
e.used = true;
this.checkToCallCallback();
@@ -25,4 +34,7 @@ mexui.Control.Button.prototype.render = function()
mexui.native.drawRectangle(pos, this.size, this.getStyles('main'));
mexui.native.drawText(pos, this.size, this.text, this.getStyles('main'));
if(this.isFocused())
mexui.native.drawRectangleBorder(mexui.util.subtractVec2(pos,new Vec2(2,2)), mexui.util.addVec2(this.size,new Vec2(3,3)), this.getStyles('focused'));
};

View File

@@ -19,11 +19,22 @@ mexui.util.linkBaseControlStyles('CheckBox', {
// input
mexui.Control.CheckBox.prototype.onMouseDown = function(e)
{
if(this.isCursorOverControl())
if(e.button == 0 && this.isCursorOverControl())
{
e.used = true;
this.checked = !this.checked;
this.checkToCallCallback();
this.toggleChecked();
}
};
mexui.Control.CheckBox.prototype.onKeyDown = function(e, key, mods)
{
if(this.isFocused())
{
if(key == SDLK_RETURN || key == SDLK_RETURN2 || key == SDLK_KP_ENTER || key == SDLK_SPACE)
{
e.used = true;
this.toggleChecked();
}
}
};
@@ -38,6 +49,9 @@ mexui.Control.CheckBox.prototype.render = function()
mexui.native.drawRectangle(mexui.util.addVec2(pos, new Vec2(1, 1)), new Vec2(this.size.x - 2, this.size.y - 2), this.getStyles('innerBox'));
mexui.native.drawText(mexui.util.addVec2(pos, new Vec2(this.size.x + this.textMarginLeft, 2)), this.size, this.text, this.getStyles('main'));
if(this.isFocused())
mexui.native.drawRectangleBorder(mexui.util.subtractVec2(pos,new Vec2(2,2)), mexui.util.addVec2(this.size,new Vec2(3,3)), this.getStyles('focused'));
};
// model
@@ -45,4 +59,10 @@ mexui.Control.CheckBox.prototype.getSizeForInput = function()
{
var textWidth = mexui.native.getTextWidth(this.text, this.getStyles('main'));
return new Vec2(this.size.x + this.textMarginLeft + textWidth, this.size.y);
};
mexui.Control.CheckBox.prototype.toggleChecked = function()
{
this.checked = !this.checked;
this.checkToCallCallback();
};

View File

@@ -9,6 +9,11 @@ mexui.util.createControlConstructor('Date', false, function(window, x, y, w, h,
this.inputShown = false;
this.valueBoxSize = new Vec2(50, 30);
this.arrowBoxSize = new Vec2(25, 22);
this.maxYearOffset = 10;
this.minYearCallback = ()=>{ return 1900; };
this.maxYearCallback = ()=>{ return new Date().getFullYear() + this.maxYearOffset; }
this.twoDigitYearCapOffset = 10;
});
mexui.util.extend(mexui.Control.Date, mexui.Control.TextInput);
@@ -51,10 +56,12 @@ mexui.Control.Date.prototype.onMouseDown = function(e)
else if(this.month == 13)
this.month = 1;
if(this.year == 1899)
this.year = 1900;
else if(this.year == 2020)
this.year = 2019;
var minYear = this.minYearCallback();
var maxYear = this.maxYearCallback();
if(this.year < minYear)
this.year = minYear;
else if(this.year > maxYear)
this.year = maxYear;
this.generateText();
@@ -113,31 +120,44 @@ mexui.Control.Date.prototype.renderAfter = function()
// model
mexui.Control.Date.prototype.generateText = function()
{
this.text = (this.day < 10 ? '0'+this.day : this.day)
this.setText((this.day < 10 ? '0'+this.day : this.day)
+'/'+(this.month < 10 ? '0'+this.month : this.month)
+'/'+(this.year < 10 ? '0'+this.year : this.year);
+'/'+(this.year < 10 ? '0'+this.year : this.year));
};
mexui.Control.Date.prototype.validateInputCallback = function(e, character)
{
var text = this.getTextWithNewCharacter(character);
var parts = text.split(':');
return mexui.util.isPositiveIntChar(character) || mexui.util.isLetter(character) || character == '/';
};
mexui.Control.Date.prototype.validateValueCallback = function(e)
{
var parts = this.getText().split('/');
if(parts.length != 3)
return false;
for(var i in parts)
{
if(i == 3)
var partAsStr = parts[i];
if(partAsStr === '')
return false;
var part = parseInt(parts[i]);
if(isNaN(part))
return false;
if(part < 0)
return false;
if(part > (i == 0 ? 23 : 59))
return false;
if(i == 0)
{
if(!mexui.util.isDayIdWithOptionalSuffix(partAsStr))
return false;
}
else if(i == 1)
{
if(!mexui.util.isMonthIdOrName(partAsStr))
return false;
}
else if(i == 2)
{
if(!mexui.util.isYear(partAsStr, this.minYearCallback(), this.maxYearCallback(), this.twoDigitYearCapOffset))
return false;
}
}
return true;

View File

@@ -7,13 +7,10 @@ mexui.util.extend(mexui.Control.Day, mexui.Control.TextInput);
// model
mexui.Control.Day.prototype.validateInputCallback = function(e, character)
{
var _int = parseInt(character);
if(isNaN(_int))
return false;
if(_int < 0 || _int > 31)
return false;
return true;
return mexui.util.isPositiveIntChar(character) || mexui.util.isLetter(character);
};
mexui.Control.Day.prototype.validateValueCallback = function(e)
{
return mexui.util.isDayIdWithOptionalSuffix(this.getText());
};

View File

@@ -30,24 +30,25 @@ mexui.util.linkBaseControlStyles('DropDown', {
// input
mexui.Control.DropDown.prototype.onMouseDown = function(e)
{
if(this.axis.y.entries.length == 0)
return;
var hitButton = this.isCursorOverControl();
if(hitButton)
if(e.button == 0)
{
e.used = true;
this.setListShown(!this.axis.y.entriesShown);
}
else if(this.axis.y.entriesShown)
{
var selectedEntryIndex = this.axis.y.getEntryIndexByCursor();
if(selectedEntryIndex != null)
if(this.axis.y.entries.length == 0)
return;
var hitButton = this.isCursorOverControl();
if(hitButton)
{
e.used = true;
this.selectedEntryIndex = selectedEntryIndex;
this.checkToCallCallback();
this.setListShown(false);
this.setListShown(!this.axis.y.entriesShown);
}
else if(this.isListShown())
{
var selectedEntryIndex = this.axis.y.getEntryIndexByCursor();
if(selectedEntryIndex != null)
{
this.selectEntryByIndex(selectedEntryIndex);
e.used = true;
}
}
}
@@ -55,6 +56,27 @@ mexui.Control.DropDown.prototype.onMouseDown = function(e)
mexui.Entity.ControlWithEntries.prototype.onMouseDown.call(this, e);
};
mexui.Control.DropDown.prototype.onKeyDown = function(e, key, mods)
{
if(this.isFocused())
{
if(key == SDLK_RETURN || key == SDLK_RETURN2 || key == SDLK_KP_ENTER || key == SDLK_SPACE)
{
var selectedEntryIndex = this.axis.y.getEntryIndexByCursor();
if(selectedEntryIndex == null)
{
this.setListShown(!this.isListShown());
e.used = true;
}
else
{
this.selectEntryByIndex(selectedEntryIndex);
e.used = true;
}
}
}
};
// render
mexui.Control.DropDown.prototype.render = function()
{
@@ -72,6 +94,9 @@ mexui.Control.DropDown.prototype.render = function()
}
mexui.Entity.ControlWithEntries.prototype.render.call(this);
if(this.isFocused())
mexui.native.drawRectangleBorder(mexui.util.subtractVec2(pos,new Vec2(2,2)), mexui.util.addVec2(this.size,new Vec2(3,3)), this.getStyles('focused'));
};
mexui.Control.DropDown.prototype.renderAfter = function()
@@ -79,10 +104,14 @@ mexui.Control.DropDown.prototype.renderAfter = function()
if(this.axis.y.entriesShown)
{
var pos = this.getScreenPosition();
var pos2 = new Vec2(pos.x, pos.y);
pos.x += this.entriesPositionOffset.x;
pos.y += this.entriesPositionOffset.y;
pos2.x += this.entriesPositionOffset.x;
pos2.y += this.entriesPositionOffset.y;
for(var i=this.axis.y.getEntryStartIndex(),j=this.axis.y.getEntryEndIndex(); i<j; i++)
{
var item = this.axis.y.entries[i];
@@ -96,6 +125,9 @@ mexui.Control.DropDown.prototype.renderAfter = function()
pos.y += this.entrySize.y;
}
if(this.isFocused())
mexui.native.drawRectangleBorder(mexui.util.subtractVec2(pos2,new Vec2(2,2)), mexui.util.addVec2(new Vec2(this.entrySize.x,this.axis.y.getDisplayedEntriesLength()),new Vec2(3,3)), this.getStyles('focused'));
}
mexui.Entity.ControlWithEntries.prototype.renderAfter.call(this);
@@ -115,3 +147,14 @@ mexui.Control.DropDown.prototype.setListShown = function(shown)
this.axis.y.setScrollBarShown(shown);
};
mexui.Control.DropDown.prototype.isListShown = function()
{
return this.axis.y.entriesShown;
};
mexui.Control.DropDown.prototype.selectEntryByIndex = function(entryIndex)
{
this.selectedEntryIndex = entryIndex;
this.checkToCallCallback();
this.setListShown(false);
};

View File

@@ -77,6 +77,9 @@ mexui.Control.Grid.prototype.render = function()
startY += row.rowHeight;
mexui.native.drawAALine(new Vec2(pos.x, startY), new Vec2(pos.x + this.size.x, startY), this.getStyles('row'));
}
if(this.isFocused())
mexui.native.drawRectangleBorder(mexui.util.subtractVec2(pos,new Vec2(2,2)), mexui.util.addVec2(this.size,new Vec2(3,3)), this.getStyles('focused'));
};
// model

View File

@@ -7,12 +7,14 @@ mexui.util.extend(mexui.Control.Hour, mexui.Control.TextInput);
// model
mexui.Control.Hour.prototype.validateInputCallback = function(e, character)
{
var _int = parseInt(character);
return mexui.util.isPositiveIntChar(character);
};
mexui.Control.Hour.prototype.validateValueCallback = function(e)
{
var _int = parseInt(this.getText());
if(isNaN(_int))
return false;
if(_int < 0 || _int > 23)
if(_int < 1 || _int > 23)
return false;
return true;

View File

@@ -14,4 +14,7 @@ mexui.Control.Image.prototype.render = function()
var pos = this.getScreenPosition();
mexui.native.drawImage(pos, this.size, this.image, this.getStyles('main'));
if(this.isFocused())
mexui.native.drawRectangleBorder(mexui.util.subtractVec2(pos,new Vec2(2,2)), mexui.util.addVec2(this.size,new Vec2(3,3)), this.getStyles('focused'));
};

View File

@@ -7,5 +7,10 @@ mexui.util.extend(mexui.Control.Integer, mexui.Control.TextInput);
// model
mexui.Control.Integer.prototype.validateInputCallback = function(e, character)
{
return !isNaN(parseInt(this.getTextWithNewCharacter(character)));
return mexui.util.isIntChar(character);
};
mexui.Control.Integer.prototype.validateValueCallback = function(e)
{
return mexui.util.isInt(this.getText());
};

View File

@@ -23,7 +23,7 @@ mexui.util.linkBaseControlStyles('List', {
// input
mexui.Control.List.prototype.onMouseDown = function(e)
{
if(this.isCursorOverControl())
if(e.button == 0 && this.isCursorOverControl())
{
this.activeRow = this.axis.y.getEntryByCursor();
this.checkToCallCallback();
@@ -34,6 +34,7 @@ mexui.Control.List.prototype.onMouseDown = function(e)
mexui.Control.List.prototype.render = function()
{
var pos = this.getScreenPosition();
var pos2 = new Vec2(pos.x, pos.y);
for(var i in this.axis.y.entries)
{
@@ -46,6 +47,9 @@ mexui.Control.List.prototype.render = function()
pos.y += this.rowHeight;
mexui.native.drawAALine(pos, new Vec2(pos.x + this.size.x, pos.y), this.getStyles('rowLine'));
}
if(this.isFocused())
mexui.native.drawRectangleBorder(mexui.util.subtractVec2(pos2,new Vec2(2,2)), mexui.util.addVec2(this.size,new Vec2(3,3)), this.getStyles('focused'));
};
// model

View File

@@ -7,12 +7,14 @@ mexui.util.extend(mexui.Control.Minute, mexui.Control.TextInput);
// model
mexui.Control.Minute.prototype.validateInputCallback = function(e, character)
{
var _int = parseInt(character);
return mexui.util.isPositiveIntChar(character);
};
mexui.Control.Minute.prototype.validateValueCallback = function(e)
{
var _int = parseInt(this.getText());
if(isNaN(_int))
return false;
if(_int < 0 || _int > 59)
if(_int < 1 || _int > 59)
return false;
return true;

View File

@@ -7,13 +7,10 @@ mexui.util.extend(mexui.Control.Month, mexui.Control.TextInput);
// model
mexui.Control.Month.prototype.validateInputCallback = function(e, character)
{
var _int = parseInt(character);
if(isNaN(_int))
return false;
if(_int < 0 || _int > 11)
return false;
return true;
return mexui.util.isPositiveIntChar(character) || mexui.util.isLetter(character);
};
mexui.Control.Month.prototype.validateValueCallback = function(e)
{
return mexui.util.isMonthIdOrName(this.getText());
};

View File

@@ -7,5 +7,10 @@ mexui.util.extend(mexui.Control.Number, mexui.Control.TextInput);
// model
mexui.Control.Number.prototype.validateInputCallback = function(e, character)
{
return !isNaN(parseFloat(this.getTextWithNewCharacter(character)));
return mexui.util.isFloatChar(character);
};
mexui.Control.Number.prototype.validateValueCallback = function(e)
{
return mexui.util.isFloat(this.getText());
};

View File

@@ -0,0 +1,16 @@
mexui.util.createControlConstructor('PositiveInteger', false, function(window, x, y, w, h, text, styles, callback)
{
mexui.Control.TextInput.call(this, window, x, y, w, h, text, this.linkControlStyles('PositiveInteger', styles), callback, false, false);
});
mexui.util.extend(mexui.Control.PositiveInteger, mexui.Control.TextInput);
// model
mexui.Control.PositiveInteger.prototype.validateInputCallback = function(e, character)
{
return mexui.util.isPositiveIntChar(character);
};
mexui.Control.PositiveInteger.prototype.validateValueCallback = function(e)
{
return mexui.util.isPositiveInt(this.getText());
};

View File

@@ -0,0 +1,16 @@
mexui.util.createControlConstructor('PositiveNumber', false, function(window, x, y, w, h, text, styles, callback)
{
mexui.Control.TextInput.call(this, window, x, y, w, h, text, this.linkControlStyles('PositiveNumber', styles), callback, false, false);
});
mexui.util.extend(mexui.Control.PositiveNumber, mexui.Control.TextInput);
// model
mexui.Control.PositiveNumber.prototype.validateInputCallback = function(e, character)
{
return mexui.util.isPositiveFloatChar(character);
};
mexui.Control.PositiveNumber.prototype.validateValueCallback = function(e)
{
return mexui.util.isPositiveFloat(this.getText());
};

View File

@@ -20,13 +20,21 @@ mexui.util.linkBaseControlStyles('RadioButton', {
// input
mexui.Control.RadioButton.prototype.onMouseDown = function(e)
{
if(this.isCursorOverControl())
if(e.button == 0 && this.isCursorOverControl())
{
var checkedRadio = this.getCheckedRadio();
if(checkedRadio != this.checked)
checkedRadio.checked = false;
this.checked = !this.checked;
this.checkToCallCallback();
this.setChecked();
}
};
mexui.Control.RadioButton.prototype.onKeyDown = function(e, key, mods)
{
if(this.isFocused())
{
if(key == SDLK_RETURN || key == SDLK_RETURN2 || key == SDLK_KP_ENTER || key == SDLK_SPACE)
{
e.used = true;
this.setChecked();
}
}
};
@@ -41,6 +49,9 @@ mexui.Control.RadioButton.prototype.render = function()
mexui.native.drawRectangle(mexui.util.addVec2(pos, new Vec2(2, 2)), new Vec2(this.size.x - 4, this.size.y - 4), this.getStyles('innerBox'));
mexui.native.drawText(mexui.util.addVec2(pos, new Vec2(this.size.x + this.textMarginLeft, 2)), this.size, this.text, this.getStyles('main'));
if(this.isFocused())
mexui.native.drawRectangleBorder(mexui.util.subtractVec2(pos,new Vec2(2,2)), mexui.util.addVec2(this.size,new Vec2(3,3)), this.getStyles('focused'));
};
// model
@@ -85,4 +96,14 @@ mexui.Control.RadioButton.prototype.getCheckedRadio = function()
mexui.Control.RadioButton.prototype.isFirstRadioInGroup = function()
{
return this.getGroupRadios().length == 0;
};
mexui.Control.RadioButton.prototype.setChecked = function()
{
var checkedRadio = this.getCheckedRadio();
if(checkedRadio != this.checked)
checkedRadio.checked = false;
this.checked = !this.checked;
this.checkToCallCallback();
};

View File

@@ -10,13 +10,15 @@ mexui.util.extend(mexui.Control.RangedInteger, mexui.Control.TextInput);
// model
mexui.Control.RangedInteger.prototype.validateInputCallback = function(e, character)
{
var number = parseInt(this.getTextWithNewCharacter(character));
if(!isNaN(number))
return mexui.util.isIntChar(character);
};
mexui.Control.RangedInteger.prototype.validateValueCallback = function(e)
{
var text = this.getText();
if(!mexui.util.isInt(text))
return false;
if(number < this.min || number > this.max)
return false;
return true;
var _int = parseInt(text);
return _int >= this.min && _int <= this.max;
};

View File

@@ -10,13 +10,15 @@ mexui.util.extend(mexui.Control.RangedNumber, mexui.Control.TextInput);
// model
mexui.Control.RangedNumber.prototype.validateInputCallback = function(e, character)
{
var number = parseFloat(this.getTextWithNewCharacter(character));
if(!isNaN(number))
return mexui.util.isFloatChar(character);
};
mexui.Control.RangedNumber.prototype.validateValueCallback = function(e)
{
var text = this.getText();
if(!mexui.util.isFloat(text))
return false;
if(number < this.min || number > this.max)
return false;
return true;
var number = parseFloat(text);
return number >= this.min && number <= this.max;
};

View File

@@ -36,22 +36,25 @@ mexui.util.linkBaseControlStyles('ScrollBar', {
// input
mexui.Control.ScrollBar.prototype.onMouseDown = function(e)
{
if(mexui.util.isCursorInRectangle(this.getInnerBarPosition(), this.getInnerBarSize()))
if(e.button == 0)
{
e.used = true;
this.isScrolling = true;
}
else if(this.isCursorOverControl())
{
e.used = true;
this.scrolledRatio += this.getScrolledRatioOuterBarClickIncrease();
this.clampScrolledRatio();
if(mexui.util.isCursorInRectangle(this.getInnerBarPosition(), this.getInnerBarSize()))
{
e.used = true;
this.isScrolling = true;
}
else if(this.isCursorOverControl())
{
e.used = true;
this.scrolledRatio += this.getScrolledRatioOuterBarClickIncrease();
this.clampScrolledRatio();
}
}
};
mexui.Control.ScrollBar.prototype.onMouseUp = function(e)
{
if(this.isScrolling)
if(e.button == 0 && this.isScrolling)
{
this.isScrolling = false;
e.used = true;

View File

@@ -7,12 +7,14 @@ mexui.util.extend(mexui.Control.Second, mexui.Control.TextInput);
// model
mexui.Control.Second.prototype.validateInputCallback = function(e, character)
{
var _int = parseInt(character);
return mexui.util.isPositiveIntChar(character);
};
mexui.Control.Second.prototype.validateValueCallback = function(e)
{
var _int = parseInt(this.getText());
if(isNaN(_int))
return false;
if(_int < 0 || _int > 59)
if(_int < 1 || _int > 59)
return false;
return true;

View File

@@ -36,7 +36,7 @@ mexui.util.linkBaseControlStyles('Slider', {
// input
mexui.Control.Slider.prototype.onMouseDown = function(e)
{
if(this.isCursorOverInnerBar())
if(e.button == 0 && this.isCursorOverInnerBar())
{
this.sliding = true;
e.used = true;
@@ -45,7 +45,7 @@ mexui.Control.Slider.prototype.onMouseDown = function(e)
mexui.Control.Slider.prototype.onMouseUp = function(e)
{
if(this.sliding)
if(e.button == 0 && this.sliding)
{
this.sliding = false;
this.checkToCallCallback();
@@ -67,6 +67,7 @@ mexui.Control.Slider.prototype.onMouseMove = function(e, offset)
mexui.Control.Slider.prototype.render = function()
{
var pos = this.getScreenPosition();
var pos2 = new Vec2(pos.x, pos.y);
mexui.native.drawRectangle(pos, this.size, this.getStyles('main'));
mexui.native.drawRectangle(this.getInnerBarPosition(), this.innerBarSize, this.getStyles('innerBar'));
@@ -81,6 +82,9 @@ mexui.Control.Slider.prototype.render = function()
pos.x += this.size.x - mexui.native.getTextWidth(this.maxText, this.getStyles('maxText'));
mexui.native.drawText(pos, this.size, this.maxText, this.getStyles('maxText'));
if(this.isFocused())
mexui.native.drawRectangleBorder(mexui.util.subtractVec2(pos2,new Vec2(2,2)), mexui.util.addVec2(this.size,new Vec2(3,3)), this.getStyles('focused'));
};
// model

View File

@@ -26,30 +26,33 @@ mexui.util.linkBaseControlStyles('TabPanel', {
// input
mexui.Control.TabPanel.prototype.onMouseDown = function(e)
{
var pos = this.getScreenPosition();
var tabX = pos.x;
for(var i in this.axis.x.entries)
if(e.button == 0)
{
var tab = this.axis.x.entries[i];
var pos = this.getScreenPosition();
var tabPos = new Vec2(tabX, pos.y);
var tabSize = new Vec2(mexui.native.getTextWidth(tab.text, this.getStyles('tab')) + 10, 25);
if(mexui.util.isCursorInRectangle(tabPos, tabSize))
var tabX = pos.x;
for(var i in this.axis.x.entries)
{
tab.setActive();
break;
var tab = this.axis.x.entries[i];
var tabPos = new Vec2(tabX, pos.y);
var tabSize = new Vec2(mexui.native.getTextWidth(tab.text, this.getStyles('tab')) + 10, 25);
if(mexui.util.isCursorInRectangle(tabPos, tabSize))
{
tab.setActive();
break;
}
tabX += tabSize.x;
}
tabX += tabSize.x;
/*
var tab = this.axis.x.getEntryByCursor();
if(tab)
tab.setActive();
*/
}
/*
var tab = this.axis.x.getEntryByCursor();
if(tab)
tab.setActive();
*/
};
// render
@@ -71,6 +74,9 @@ mexui.Control.TabPanel.prototype.render = function()
tabX += tabSize.x;
}
if(this.isFocused())
mexui.native.drawRectangleBorder(mexui.util.subtractVec2(pos,new Vec2(2,2)), mexui.util.addVec2(this.size,new Vec2(3,3)), this.getStyles('focused'));
};
// model

View File

@@ -14,4 +14,7 @@ mexui.Control.Text.prototype.render = function()
var pos = this.getScreenPosition();
mexui.native.drawText(pos, this.size, this.text, this.getStyles('main'));
if(this.isFocused())
mexui.native.drawRectangleBorder(mexui.util.subtractVec2(pos,new Vec2(2,2)), mexui.util.addVec2(this.size,new Vec2(3,3)), this.getStyles('focused'));
};

View File

@@ -17,6 +17,8 @@ mexui.util.createControlConstructor('TextInput', false, function(window, x, y, w
this.caretShownForBlink = true;
this.lineHeight = 25;
this.maxLength = this.singleCharacter ? 1 : false;
this.validValue = true;
});
// default styles
@@ -34,10 +36,13 @@ mexui.util.linkBaseControlStyles('TextInput', {
// input
mexui.Control.TextInput.prototype.onMouseDown = function(e)
{
var hit = this.isCursorOverControl();
if(hit)
if(e.button == 0)
{
this.caretPosition = this.getCaretPositionByCursor();
var hit = this.isCursorOverControl();
if(hit)
{
this.caretPosition = this.getCaretPositionByCursor();
}
}
mexui.Component.Control.prototype.onMouseDown.call(this, e);
@@ -70,6 +75,7 @@ mexui.Control.TextInput.prototype.onCharacter = function(e, character)
}
this.checkToCallCallback();
this.validateValue(e);
}
};
@@ -193,12 +199,16 @@ mexui.Control.TextInput.prototype.onKeyDown = function(e, key, mods)
break;
}
}
this.validateValue(e);
};
// render
mexui.Control.TextInput.prototype.render = function()
{
var pos = this.getScreenPosition();
var pos2 = new Vec2(pos.x, pos.y);
mexui.native.drawRectangle(pos, this.size, this.getStyles('main'));
if(this.isEmpty())
@@ -217,22 +227,31 @@ mexui.Control.TextInput.prototype.render = function()
}
}
if(mexui.focusedControl == this && this.caretShownForBlink)
var valueIsInvalid = !this.isEmpty() && !this.validValue;
if(this.isFocused())
{
var pos = this.getScreenPosition();
var text = this.lines[this.caretPosition.y].substr(0, this.caretPosition.x);
var displayedText = this.masked ? '*'.repeat(text.length) : text;
var textWidth = mexui.native.getTextWidth(displayedText, this.getStyles('main'));
var caretPosOffset = new Vec2(5 + textWidth, (this.caretPosition.y * this.lineHeight) + 1);
var caretPoint1 = mexui.util.addVec2(pos, caretPosOffset);
var caretPoint2 = new Vec2(caretPoint1.x, caretPoint1.y + 22);
mexui.native.drawAALine(caretPoint1, caretPoint2, this.getStyles('caret'));
if(!valueIsInvalid)
mexui.native.drawRectangleBorder(mexui.util.subtractVec2(pos2,new Vec2(2,2)), mexui.util.addVec2(this.size,new Vec2(3,3)), this.getStyles('focused'));
if(this.caretShownForBlink)
{
var pos = this.getScreenPosition();
var text = this.lines[this.caretPosition.y].substr(0, this.caretPosition.x);
var displayedText = this.masked ? '*'.repeat(text.length) : text;
var textWidth = mexui.native.getTextWidth(displayedText, this.getStyles('main'));
var caretPosOffset = new Vec2(5 + textWidth, (this.caretPosition.y * this.lineHeight) + 1);
var caretPoint1 = mexui.util.addVec2(pos, caretPosOffset);
var caretPoint2 = new Vec2(caretPoint1.x, caretPoint1.y + 22);
mexui.native.drawAALine(caretPoint1, caretPoint2, this.getStyles('caret'));
}
}
if(valueIsInvalid)
mexui.native.drawRectangleBorder(mexui.util.subtractVec2(pos2,new Vec2(2,2)), mexui.util.addVec2(this.size,new Vec2(3,3)), this.getStyles('invalidValue'));
};
// model
mexui.Control.TextInput.prototype.getTextWithNewCharacter = function(character)
{
return this.lines[this.caretPosition.y].substr(0, this.caretPosition.x) + character + this.lines[this.caretPosition.y].substr(this.caretPosition.x);
@@ -335,6 +354,16 @@ mexui.Control.TextInput.prototype.deleteCharacter = function(charPos)
};
// text overall
mexui.Control.TextInput.prototype.setText = function(text)
{
this.lines = mexui.util.splitLines(text);
};
mexui.Control.TextInput.prototype.getText = function()
{
return this.lines.join("\r\n");
};
mexui.Control.TextInput.prototype.resetText = function()
{
this.lines = [''];
@@ -345,3 +374,8 @@ mexui.Control.TextInput.prototype.isEmpty = function()
return this.lines.length == 1 && this.lines[0] == '';
};
// validation
mexui.Control.TextInput.prototype.validateValue = function(e)
{
this.validValue = this.validateValueCallback ? this.validateValueCallback(e) : true;
};

View File

@@ -102,24 +102,35 @@ mexui.Control.Time.prototype.renderAfter = function()
// model
mexui.Control.Time.prototype.generateText = function()
{
this.text = (this.hour < 10 ? '0'+this.hour : this.hour)
this.setText((this.hour < 10 ? '0'+this.hour : this.hour)
+':'+(this.minute < 10 ? '0'+this.minute : this.minute)
+':'+(this.second < 10 ? '0'+this.second : this.second);
+':'+(this.second < 10 ? '0'+this.second : this.second));
};
mexui.Control.Time.prototype.validateInputCallback = function(e, character)
{
var text = this.getTextWithNewCharacter(character);
var parts = text.split(':');
return mexui.util.isPositiveIntChar(character) || character == ':';
};
mexui.Control.Time.prototype.validateValueCallback = function(e)
{
var parts = this.getText().split(':');
if(parts.length != 3)
return false;
for(var i in parts)
{
if(i == 3)
var partAsStr = parts[i];
if(partAsStr === '')
return false;
var part = parseInt(parts[i]);
var part = parseInt(partAsStr);
if(isNaN(part))
if(partAsStr.length == 2 && partAsStr.substr(0, 1) == '0')
partAsStr = partAsStr.substr(1);
if(!mexui.util.isPositiveInt(partAsStr))
return false;
if(part < 0)

View File

@@ -28,10 +28,13 @@ mexui.util.linkBaseControlStyles('Tree', {
// input
mexui.Control.Tree.prototype.onMouseDown = function(e)
{
var pos = this.getScreenPosition();
pos.y -= this.axis.y.getScrolledOffset();
this.testRowClick(e, this.axis.y.entries, pos);
if(e.button == 0)
{
var pos = this.getScreenPosition();
pos.y -= this.axis.y.getScrolledOffset();
this.testRowClick(e, this.axis.y.entries, pos);
}
if(!e.used)
mexui.Entity.ControlWithEntries.prototype.onMouseDown.call(this, e);
@@ -44,6 +47,9 @@ mexui.Control.Tree.prototype.render = function()
pos.y -= this.axis.y.getScrolledOffset();
this.renderRows(this.axis.y.entries, 0, pos);
if(this.isFocused())
mexui.native.drawRectangleBorder(mexui.util.subtractVec2(pos,new Vec2(2,2)), mexui.util.addVec2(this.size,new Vec2(3,3)), this.getStyles('focused'));
};
mexui.Control.Tree.prototype.renderRows = function(rows, level, pos)

View File

@@ -7,12 +7,14 @@ mexui.util.extend(mexui.Control.Week, mexui.Control.TextInput);
// model
mexui.Control.Week.prototype.validateInputCallback = function(e, character)
{
var _int = parseInt(character);
return mexui.util.isPositiveIntChar(character);
};
mexui.Control.Week.prototype.validateValueCallback = function(e)
{
var _int = parseInt(this.getText());
if(isNaN(_int))
return false;
if(_int < 0 || _int > 51)
if(_int < 1 || _int > 52)
return false;
return true;

View File

@@ -0,0 +1,16 @@
mexui.util.createControlConstructor('WeekDay', false, function(window, x, y, w, h, text, styles, callback)
{
mexui.Control.TextInput.call(this, window, x, y, w, h, text, this.linkControlStyles('WeekDay', styles), callback, false, false);
});
mexui.util.extend(mexui.Control.WeekDay, mexui.Control.TextInput);
// model
mexui.Control.WeekDay.prototype.validateInputCallback = function(e, character)
{
return mexui.util.isPositiveIntChar(character) || mexui.util.isLetter(character);
};
mexui.Control.WeekDay.prototype.validateValueCallback = function(e)
{
return mexui.util.isWeekDayIdOrName(this.getText());
};

View File

@@ -1,19 +1,21 @@
mexui.util.createControlConstructor('Year', false, function(window, x, y, w, h, text, styles, callback)
{
mexui.Control.TextInput.call(this, window, x, y, w, h, text, this.linkControlStyles('Year', styles), callback, false, false);
this.maxYearOffset = 10;
this.minYearCallback = ()=>{ return 1900; };
this.maxYearCallback = ()=>{ return new Date().getFullYear() + this.maxYearOffset; }
this.twoDigitYearCapOffset = 10;
});
mexui.util.extend(mexui.Control.Year, mexui.Control.TextInput);
// model
mexui.Control.Year.prototype.validateInputCallback = function(e, character)
{
var _int = parseInt(character);
if(isNaN(_int))
return false;
if(_int < 1900 || _int > 2019)
return false;
return true;
return mexui.util.isPositiveIntChar(character);
};
mexui.Control.Year.prototype.validateValueCallback = function(e)
{
return mexui.util.isYear(this.getText(), this.minYearCallback(), this.maxYearCallback(), this.twoDigitYearCapOffset);
};

View File

@@ -9,7 +9,7 @@ mexui.util.extend(mexui.Entity.Component, mexui.Entity.StyleableEntity);
// input
mexui.Entity.Component.prototype.onMouseDown = function(e)
{
if(this.moveable && this.isCursorOverComponent())
if(e.button == 0 && this.moveable && this.isCursorOverComponent())
{
this.moving = true;
e.used = true;
@@ -18,7 +18,7 @@ mexui.Entity.Component.prototype.onMouseDown = function(e)
mexui.Entity.Component.prototype.onMouseUp = function(e)
{
if(this.moving)
if(e.button == 0 && this.moving)
{
this.moving = false;
e.used = true;

View File

@@ -53,6 +53,14 @@ mexui.Entity.StyleableEntity.defaultStyles = mexui.util.linkGlobalStyles(mexui.E
textColour: toColour(0, 0, 0, 255)
}
*/
},
focused:
{
borderColour: toColour(28, 119, 198, 255)
},
invalidValue:
{
borderColour: toColour(250, 5, 5, 255)
}
});

View File

@@ -10,7 +10,19 @@ mexui.native.loadImage = function(imageFilePath, imageName)
return false;
}
var image = drawing.loadPNG(file);
var image = null;
var parts = imageFilePath.split('.');
var ext = parts[parts.length - 1].toLowerCase();
if(ext == 'png')
image = drawing.loadPNG(file);
else if(ext == 'bmp')
image = drawing.loadBMP(file);
else
{
console.log('ERROR [IMAGE LOAD] - Unsupported image file path extension. Currently only supports PNG or BMP.');
return false;
}
if(!image)
{
file.close();
@@ -121,9 +133,6 @@ mexui.native.drawAALine = function(point1, point2, styles)
if(lineColour == null || lineColour == 'none')
return;
//console.log(typeof lineColour);
//console.log(lineColour);
drawing.drawRectangle(null, point1, new Vec2((point2.x - point1.x) + styles.lineWeight, (point2.y - point1.y) + styles.lineWeight), lineColour, lineColour, lineColour, lineColour);
};

View File

@@ -1,5 +1,10 @@
mexui.util = {};
// static
mexui.util.monthNames = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'];
mexui.util.weekDayNames = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'];
// functions
mexui.util.extend = function(d, b)
{
d.prototype = Object.create(b.prototype);
@@ -24,6 +29,11 @@ mexui.util.addVec2 = function(vec2a, vec2b)
return new Vec2(vec2a.x + vec2b.x, vec2a.y + vec2b.y);
};
mexui.util.subtractVec2 = function(vec2a, vec2b)
{
return new Vec2(vec2a.x - vec2b.x, vec2a.y - vec2b.y);
};
mexui.util.addVec3 = function(vec3a, vec3b)
{
return new Vec3(vec3a.x + vec3b.x, vec3a.y + vec3b.y, vec3a.z + vec3b.z);
@@ -469,3 +479,226 @@ mexui.util.time = function()
return gta.tickCount;
};
mexui.util.isIntChar = function(character)
{
return mexui.util.isPositiveIntChar(character);
};
mexui.util.isPositiveIntChar = function(character)
{
return mexui.util.isDigit(character) || character == '-' || character == '+' || character == 'e' || character == 'E';
};
mexui.util.isFloatChar = function(character)
{
return mexui.util.isIntChar(character) || character == '.';
};
mexui.util.isPositiveFloatChar = function(character)
{
return mexui.util.isPositiveIntChar(character) || character == '.';
};
mexui.util.isInt = function(str)
{
var strInt = parseInt(str);
return !isNaN(strInt) && str.length == (strInt+'').length;
};
mexui.util.isPositiveInt = function(str)
{
var strInt = parseInt(str);
return !isNaN(strInt) && strInt >= 0 && str.length == (strInt+'').length;
};
mexui.util.isFloat = function(str)
{
var strFloat = parseFloat(str);
var firstDot = str.indexOf('.');
var addOffset = (str.substr(str.length - 2, 2) == '.0' && firstDot == (str.length - 2)) ? 2 : 0;
if(firstDot == 0)
addOffset--;
return !isNaN(strFloat) && str.length == ((strFloat+'').length + addOffset);
};
mexui.util.isPositiveFloat = function(str)
{
var strFloat = parseFloat(str);
var firstDot = str.indexOf('.');
var addOffset = (str.substr(str.length - 2, 2) == '.0' && firstDot == (str.length - 2)) ? 2 : 0;
if(firstDot == 0)
addOffset--;
return !isNaN(strFloat) && strFloat >= 0.0 && str.length == ((strFloat+'').length + addOffset);
};
mexui.util.isMonthName = function(text)
{
return mexui.util.inArrayOrStartsWithInArray(text, mexui.util.monthNames, 3);
};
mexui.util.isWeekDayName = function(text)
{
return mexui.util.inArrayOrStartsWithInArray(text, mexui.util.weekDayNames, 3);
};
mexui.util.isDayIdSuffix = function(text)
{
switch(text.toLowerCase())
{
case 'st':
case 'nd':
case 'rd':
case 'th':
return true;
}
return false;
};
mexui.util.isDayIdSuffixForDayId = function(dayId, text)
{
switch(text.toLowerCase())
{
case 'st': return dayId == 1 || dayId == 21 || dayId == 31;
case 'nd': return dayId == 2 || dayId == 22;
case 'rd': return dayId == 3 || dayId == 23;
case 'th': return !(dayId >= 1 && dayId <= 3) && !(dayId >= 21 && dayId <= 23) && dayId != 31;
default: return false;
}
};
mexui.util.isDayId = function(text)
{
if(text.length == 2 && text.substr(0, 1) == '0')
text = text.substr(1);
if(mexui.util.isPositiveInt(text))
{
var _int = parseInt(text);
if(_int >= 1 && _int <= 31)
return true;
}
return false;
};
mexui.util.isDayIdWithOptionalSuffix = function(text)
{
if(mexui.util.isDayId(text))
return true;
if(text.length > 2)
{
var last2Chars = text.substr(text.length - 2, 2);
if(mexui.util.isDayIdSuffix(last2Chars))
{
var textWithoutLast2Chars = text.substr(0, text.length - 2);
if(mexui.util.isDayId(textWithoutLast2Chars) && mexui.util.isDayIdSuffixForDayId(parseInt(textWithoutLast2Chars), last2Chars))
{
return true;
}
}
}
return false;
};
mexui.util.inArrayOrStartsWithInArray = function(text, arr, startsWithCharCount)
{
text = text.toLowerCase();
for(var i in arr)
{
if(text === arr[i])
{
return true;
}
}
if(text.length == startsWithCharCount)
{
for(var i in arr)
{
if(text === arr[i].substr(0, startsWithCharCount))
{
return true;
}
}
}
return false;
};
mexui.util.isMonthIdOrName = function(text)
{
var text2 = text;
if(text2.length == 2 && text2.substr(0, 1) == '0')
text2 = text2.substr(1);
if(mexui.util.isPositiveInt(text2))
{
var _int = parseInt(text2);
if(_int >= 1 && _int <= 12)
return true;
}
return mexui.util.isMonthName(text);
};
mexui.util.isWeekDayId = function(text)
{
var text2 = text;
if(text2.length == 2 && text2.substr(0, 1) == '0')
text2 = text2.substr(1);
if(mexui.util.isPositiveInt(text2))
{
var _int = parseInt(text2);
if(_int >= 1 && _int <= 7)
return true;
}
return false;
};
mexui.util.isWeekDayIdOrName = function(text)
{
var text2 = text;
if(text2.length == 2 && text2.substr(0, 1) == '0')
text2 = text2.substr(1);
if(mexui.util.isPositiveInt(text2))
{
var _int = parseInt(text2);
if(_int >= 1 && _int <= 7)
return true;
}
return mexui.util.isWeekDayName(text);
};
mexui.util.expand2DigitYear = function(year, twoDigitYearCapOffset)
{
var currentFullYear = new Date().getFullYear();
var currentTwoDigitYearPlusCapOffset = parseInt((currentFullYear+'').substr(2, 2)) + twoDigitYearCapOffset;
if(year <= currentTwoDigitYearPlusCapOffset)
year += currentFullYear - (currentFullYear % 100);
else
year += (currentFullYear - (currentFullYear % 100)) - 100;
return year;
};
mexui.util.isYear = function(text, minYear, maxYear, twoDigitYearCapOffset)
{
var _int = parseInt(text);
if(isNaN(_int))
return false;
if(_int >= 0 && _int <= 99)
_int = mexui.util.expand2DigitYear(_int, twoDigitYearCapOffset);
if(_int < minYear || _int > maxYear)
return false;
return true;
};