mirror of https://github.com/anoshenko/rui.git
Added TableView cell/row selection mode
This commit is contained in:
parent
15a11dc558
commit
1a4040bd00
|
@ -1,3 +1,7 @@
|
|||
# v0.5.0
|
||||
|
||||
* Added HasFocus function to the View interface
|
||||
|
||||
# v0.4.0
|
||||
|
||||
* Added SetTitle and SetTitleColor function to the Session interface
|
||||
|
|
485
app_scripts.js
485
app_scripts.js
|
@ -615,12 +615,13 @@ function selectDropDownListItem(elementId, number) {
|
|||
|
||||
function listItemClickEvent(element, event) {
|
||||
event.stopPropagation();
|
||||
|
||||
var selected = false;
|
||||
if (element.classList) {
|
||||
selected = (element.classList.contains("ruiListItemFocused") || element.classList.contains("ruiListItemSelected"));
|
||||
} else {
|
||||
selected = element.className.indexOf("ruiListItemFocused") >= 0 || element.className.indexOf("ruiListItemSelected") >= 0;
|
||||
}
|
||||
const focusStyle = getListFocusedItemStyle(element);
|
||||
const blurStyle = getListSelectedItemStyle(element);
|
||||
selected = (element.classList.contains(focusStyle) || element.classList.contains(blurStyle));
|
||||
}
|
||||
|
||||
var list = element.parentNode.parentNode
|
||||
if (list) {
|
||||
|
@ -640,18 +641,27 @@ function getListItemNumber(itemId) {
|
|||
}
|
||||
}
|
||||
|
||||
function getStyleAttribute(element, attr, defValue) {
|
||||
var result = element.getAttribute(attr);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
return defValue;
|
||||
}
|
||||
|
||||
function getListFocusedItemStyle(element) {
|
||||
return getStyleAttribute(element, "data-focusitemstyle", "ruiListItemFocused");
|
||||
}
|
||||
|
||||
function getListSelectedItemStyle(element) {
|
||||
return getStyleAttribute(element, "data-bluritemstyle", "ruiListItemSelected");
|
||||
}
|
||||
|
||||
function selectListItem(element, item, needSendMessage) {
|
||||
var currentId = element.getAttribute("data-current");
|
||||
var message;
|
||||
var focusStyle = element.getAttribute("data-focusitemstyle");
|
||||
var blurStyle = element.getAttribute("data-bluritemstyle");
|
||||
|
||||
if (!focusStyle) {
|
||||
focusStyle = "ruiListItemFocused"
|
||||
}
|
||||
if (!blurStyle) {
|
||||
blurStyle = "ruiListItemSelected"
|
||||
}
|
||||
const focusStyle = getListFocusedItemStyle(element);
|
||||
const blurStyle = getListSelectedItemStyle(element);
|
||||
|
||||
if (currentId) {
|
||||
var current = document.getElementById(currentId);
|
||||
|
@ -801,24 +811,29 @@ function findBottomListItem(list, x, y) {
|
|||
return result
|
||||
}
|
||||
|
||||
function listViewKeyDownEvent(element, event) {
|
||||
var key;
|
||||
function getKey(event) {
|
||||
if (event.key) {
|
||||
key = event.key;
|
||||
} else if (event.keyCode) {
|
||||
return event.key;
|
||||
}
|
||||
|
||||
if (event.keyCode) {
|
||||
switch (event.keyCode) {
|
||||
case 13: key = "Enter"; break;
|
||||
case 32: key = " "; break;
|
||||
case 33: key = "PageUp"; break;
|
||||
case 34: key = "PageDown"; break;
|
||||
case 35: key = "End"; break;
|
||||
case 36: key = "Home"; break;
|
||||
case 37: key = "ArrowLeft"; break;
|
||||
case 38: key = "ArrowUp"; break;
|
||||
case 39: key = "ArrowRight"; break;
|
||||
case 40: key = "ArrowDown"; break;
|
||||
case 13: return "Enter";
|
||||
case 32: return " ";
|
||||
case 33: return "PageUp";
|
||||
case 34: return "PageDown";
|
||||
case 35: return "End";
|
||||
case 36: return "Home";
|
||||
case 37: return "ArrowLeft";
|
||||
case 38: return "ArrowUp";
|
||||
case 39: return "ArrowRight";
|
||||
case 40: return "ArrowDown";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function listViewKeyDownEvent(element, event) {
|
||||
const key = getKey(event);
|
||||
if (key) {
|
||||
var currentId = element.getAttribute("data-current");
|
||||
var current
|
||||
|
@ -885,21 +900,10 @@ function listViewFocusEvent(element, event) {
|
|||
if (currentId) {
|
||||
var current = document.getElementById(currentId);
|
||||
if (current) {
|
||||
var focusStyle = element.getAttribute("data-focusitemstyle");
|
||||
var blurStyle = element.getAttribute("data-bluritemstyle");
|
||||
if (!focusStyle) {
|
||||
focusStyle = "ruiListItemFocused"
|
||||
}
|
||||
if (!blurStyle) {
|
||||
blurStyle = "ruiListItemSelected"
|
||||
}
|
||||
|
||||
if (current.classList) {
|
||||
current.classList.remove(blurStyle);
|
||||
current.classList.add(focusStyle);
|
||||
} else { // IE < 10
|
||||
current.className = "ruiListItem " + focusStyle;
|
||||
}
|
||||
current.classList.remove(getListSelectedItemStyle(element));
|
||||
current.classList.add(getListFocusedItemStyle(element));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -909,20 +913,9 @@ function listViewBlurEvent(element, event) {
|
|||
if (currentId) {
|
||||
var current = document.getElementById(currentId);
|
||||
if (current) {
|
||||
var focusStyle = element.getAttribute("data-focusitemstyle");
|
||||
var blurStyle = element.getAttribute("data-bluritemstyle");
|
||||
if (!focusStyle) {
|
||||
focusStyle = "ruiListItemFocused"
|
||||
}
|
||||
if (!blurStyle) {
|
||||
blurStyle = "ruiListItemSelected"
|
||||
}
|
||||
|
||||
if (current.classList) {
|
||||
current.classList.remove(focusStyle);
|
||||
current.classList.add(blurStyle);
|
||||
} else { // IE < 10
|
||||
current.className = "ruiListItem " + blurStyle;
|
||||
current.classList.remove(getListFocusedItemStyle(element));
|
||||
current.classList.add(getListSelectedItemStyle(element));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1372,4 +1365,388 @@ function setTitleColor(color) {
|
|||
|
||||
function detailsEvent(element) {
|
||||
sendMessage("details-open{session=" + sessionID + ",id=" + element.id + ",open=" + (element.open ? "1}" : "0}"));
|
||||
}
|
||||
|
||||
function getTableFocusedItemStyle(element) {
|
||||
return getStyleAttribute(element, "data-focusitemstyle", "ruiCurrentTableCellFocused");
|
||||
}
|
||||
|
||||
function getTableSelectedItemStyle(element) {
|
||||
return getStyleAttribute(element, "data-bluritemstyle", "ruiCurrentTableCell");
|
||||
}
|
||||
|
||||
function tableViewFocusEvent(element, event) {
|
||||
var currentId = element.getAttribute("data-current");
|
||||
if (currentId) {
|
||||
var current = document.getElementById(currentId);
|
||||
if (current) {
|
||||
if (current.classList) {
|
||||
current.classList.remove(getTableSelectedItemStyle(element));
|
||||
current.classList.add(getTableFocusedItemStyle(element));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function tableViewBlurEvent(element, event) {
|
||||
var currentId = element.getAttribute("data-current");
|
||||
if (currentId) {
|
||||
var current = document.getElementById(currentId);
|
||||
if (current && current.classList) {
|
||||
current.classList.remove(getTableFocusedItemStyle(element));
|
||||
current.classList.add(getTableSelectedItemStyle(element));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setTableCellCursor(element, row, column) {
|
||||
const cellID = element.id + "-" + row + "-" + column;
|
||||
var cell = document.getElementById(cellID);
|
||||
if (!cell) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const focusStyle = getTableFocusedItemStyle(element);
|
||||
const oldCellID = element.getAttribute("data-current");
|
||||
if (oldCellID) {
|
||||
const oldCell = document.getElementById(oldCellID);
|
||||
if (oldCell && oldCell.classList) {
|
||||
oldCell.classList.remove(focusStyle);
|
||||
oldCell.classList.remove(getTableSelectedItemStyle(element));
|
||||
}
|
||||
}
|
||||
|
||||
cell.classList.add(focusStyle);
|
||||
element.setAttribute("data-current", cellID);
|
||||
|
||||
sendMessage("currentCell{session=" + sessionID + ",id=" + element.id +
|
||||
",row=" + row + ",column=" + column + "}");
|
||||
return true;
|
||||
}
|
||||
|
||||
function moveTableCellCursor(element, row, column, dr, dc) {
|
||||
const rows = element.getAttribute("data-rows");
|
||||
if (!rows) {
|
||||
return;
|
||||
}
|
||||
const columns = element.getAttribute("data-columns");
|
||||
if (!columns) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rowCount = parseInt(rows);
|
||||
const columnCount = parseInt(columns);
|
||||
|
||||
row += dr;
|
||||
column += dc;
|
||||
while (row >= 0 && row < rowCount && column >= 0 && column < columnCount) {
|
||||
if (setTableCellCursor(element, row, column)) {
|
||||
return;
|
||||
} else if (dr == 0) {
|
||||
var r2 = row - 1;
|
||||
while (r2 >= 0) {
|
||||
if (setTableCellCursor(element, r2, column)) {
|
||||
return;
|
||||
}
|
||||
r2--;
|
||||
}
|
||||
} else if (dc == 0) {
|
||||
var c2 = column - 1;
|
||||
while (c2 >= 0) {
|
||||
if (setTableCellCursor(element, row, c2)) {
|
||||
return;
|
||||
}
|
||||
c2--;
|
||||
}
|
||||
}
|
||||
row += dr;
|
||||
column += dc;
|
||||
}
|
||||
}
|
||||
|
||||
function tableViewCellKeyDownEvent(element, event) {
|
||||
const key = getKey(event);
|
||||
if (key) {
|
||||
const currentId = element.getAttribute("data-current");
|
||||
if (currentId) {
|
||||
const elements = currentId.split("-");
|
||||
if (elements.length >= 3) {
|
||||
const row = parseInt(elements[1], 10)
|
||||
const column = parseInt(elements[2], 10)
|
||||
|
||||
switch (key) {
|
||||
case " ":
|
||||
case "Enter":
|
||||
sendMessage("cellClick{session=" + sessionID + ",id=" + element.id +
|
||||
",row=" + row + ",column=" + column + "}");
|
||||
break;
|
||||
|
||||
case "ArrowLeft":
|
||||
moveTableCellCursor(element, row, column, 0, -1)
|
||||
break;
|
||||
|
||||
case "ArrowRight":
|
||||
moveTableCellCursor(element, row, column, 0, 1)
|
||||
break;
|
||||
|
||||
case "ArrowDown":
|
||||
moveTableCellCursor(element, row, column, 1, 0)
|
||||
break;
|
||||
|
||||
case "ArrowUp":
|
||||
moveTableCellCursor(element, row, column, -1, 0)
|
||||
break;
|
||||
|
||||
case "Home":
|
||||
// TODO
|
||||
break;
|
||||
|
||||
case "End":
|
||||
/*var newRow = rowCount-1;
|
||||
while (newRow > row) {
|
||||
if (setTableRowCursor(element, newRow)) {
|
||||
break;
|
||||
}
|
||||
newRow--;
|
||||
}*/
|
||||
// TODO
|
||||
break;
|
||||
|
||||
case "PageUp":
|
||||
// TODO
|
||||
break;
|
||||
|
||||
case "PageDown":
|
||||
// TODO
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
case "ArrowLeft":
|
||||
case "ArrowRight":
|
||||
case "ArrowDown":
|
||||
case "ArrowUp":
|
||||
case "Home":
|
||||
case "End":
|
||||
case "PageUp":
|
||||
case "PageDown":
|
||||
const rows = element.getAttribute("data-rows");
|
||||
const columns = element.getAttribute("data-columns");
|
||||
if (rows && columns) {
|
||||
const rowCount = parseInt(rows);
|
||||
const columnCount = parseInt(rows);
|
||||
row = 0;
|
||||
while (row < rowCount) {
|
||||
column = 0;
|
||||
while (columns < columnCount) {
|
||||
if (setTableCellCursor(element, row, column)) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
column++;
|
||||
}
|
||||
row++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
function setTableRowCursor(element, row) {
|
||||
const tableRowID = element.id + "-" + row;
|
||||
var tableRow = document.getElementById(tableRowID);
|
||||
if (!tableRow) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const focusStyle = getTableFocusedItemStyle(element);
|
||||
const oldRowID = element.getAttribute("data-current");
|
||||
if (oldRowID) {
|
||||
const oldRow = document.getElementById(oldRowID);
|
||||
if (oldRow && oldRow.classList) {
|
||||
oldRow.classList.remove(focusStyle);
|
||||
oldRow.classList.remove(getTableSelectedItemStyle(element));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
tableRow.classList.add(focusStyle);
|
||||
element.setAttribute("data-current", tableRowID);
|
||||
|
||||
sendMessage("currentRow{session=" + sessionID + ",id=" + element.id + ",row=" + row + "}");
|
||||
return true;
|
||||
}
|
||||
|
||||
function moveTableRowCursor(element, row, dr) {
|
||||
const rows = element.getAttribute("data-rows");
|
||||
if (!rows) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rowCount = parseInt(rows);
|
||||
row += dr;
|
||||
while (row >= 0 && row < rowCount) {
|
||||
if (setTableRowCursor(element, row)) {
|
||||
return;
|
||||
}
|
||||
row += dr;
|
||||
}
|
||||
}
|
||||
|
||||
function tableViewRowKeyDownEvent(element, event) {
|
||||
const key = getKey(event);
|
||||
if (key) {
|
||||
const currentId = element.getAttribute("data-current");
|
||||
if (currentId) {
|
||||
const elements = currentId.split("-");
|
||||
if (elements.length >= 2) {
|
||||
const row = parseInt(elements[1], 10);
|
||||
switch (key) {
|
||||
case " ":
|
||||
case "Enter":
|
||||
sendMessage("rowClick{session=" + sessionID + ",id=" + element.id + ",row=" + row + "}");
|
||||
break;
|
||||
|
||||
case "ArrowDown":
|
||||
moveTableRowCursor(element, row, 1)
|
||||
break;
|
||||
|
||||
case "ArrowUp":
|
||||
moveTableRowCursor(element, row, -1)
|
||||
break;
|
||||
|
||||
case "Home":
|
||||
var newRow = 0;
|
||||
while (newRow < row) {
|
||||
if (setTableRowCursor(element, newRow)) {
|
||||
break;
|
||||
}
|
||||
newRow++;
|
||||
}
|
||||
break;
|
||||
|
||||
case "End":
|
||||
var newRow = rowCount-1;
|
||||
while (newRow > row) {
|
||||
if (setTableRowCursor(element, newRow)) {
|
||||
break;
|
||||
}
|
||||
newRow--;
|
||||
}
|
||||
break;
|
||||
|
||||
case "PageUp":
|
||||
// TODO
|
||||
break;
|
||||
|
||||
case "PageDown":
|
||||
// TODO
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
case "ArrowLeft":
|
||||
case "ArrowRight":
|
||||
case "ArrowDown":
|
||||
case "ArrowUp":
|
||||
case "Home":
|
||||
case "End":
|
||||
case "PageUp":
|
||||
case "PageDown":
|
||||
const rows = element.getAttribute("data-rows");
|
||||
if (rows) {
|
||||
const rowCount = parseInt(rows);
|
||||
row = 0;
|
||||
while (row < rowCount) {
|
||||
if (setTableRowCursor(element, row)) {
|
||||
break;
|
||||
}
|
||||
row++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
function tableCellClickEvent(element, event) {
|
||||
event.preventDefault();
|
||||
|
||||
const elements = element.id.split("-");
|
||||
if (elements.length < 3) {
|
||||
return
|
||||
}
|
||||
|
||||
const tableID = elements[0];
|
||||
const row = parseInt(elements[1], 10);
|
||||
const column = parseInt(elements[2], 10);
|
||||
const table = document.getElementById(tableID);
|
||||
if (table) {
|
||||
const selection = table.getAttribute("data-selection");
|
||||
if (selection == "cell") {
|
||||
const currentID = table.getAttribute("data-current");
|
||||
if (!currentID || currentID != element.ID) {
|
||||
setTableCellCursor(table, row, column)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sendMessage("cellClick{session=" + sessionID + ",id=" + tableID +
|
||||
",row=" + row + ",column=" + column + "}");
|
||||
}
|
||||
|
||||
function tableRowClickEvent(element, event) {
|
||||
event.preventDefault();
|
||||
|
||||
const elements = element.id.split("-");
|
||||
if (elements.length < 2) {
|
||||
return
|
||||
}
|
||||
|
||||
const tableID = elements[0];
|
||||
const row = parseInt(elements[1], 10);
|
||||
const table = document.getElementById(tableID);
|
||||
if (table) {
|
||||
const selection = table.getAttribute("data-selection");
|
||||
if (selection == "cell") {
|
||||
const currentID = table.getAttribute("data-current");
|
||||
if (!currentID || currentID != element.ID) {
|
||||
setTableRowCursor(table, row)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sendMessage("rowClick{session=" + sessionID + ",id=" + tableID + ",row=" + row + "}");
|
||||
}
|
|
@ -148,11 +148,15 @@ func (customView *CustomViewData) Scroll() Frame {
|
|||
return customView.superView.Scroll()
|
||||
}
|
||||
|
||||
func (customView *CustomViewData) HasFocus() bool {
|
||||
return customView.superView.HasFocus()
|
||||
}
|
||||
|
||||
func (customView *CustomViewData) onResize(self View, x, y, width, height float64) {
|
||||
customView.superView.onResize(customView.superView, x, y, width, height)
|
||||
}
|
||||
|
||||
func (customView *CustomViewData) onItemResize(self View, index int, x, y, width, height float64) {
|
||||
func (customView *CustomViewData) onItemResize(self View, index string, x, y, width, height float64) {
|
||||
customView.superView.onItemResize(customView.superView, index, x, y, width, height)
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,10 @@ func (picker *datePickerData) Init(session Session) {
|
|||
picker.dateChangedListeners = []func(DatePicker, time.Time){}
|
||||
}
|
||||
|
||||
func (picker *datePickerData) Focusable() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (picker *datePickerData) normalizeTag(tag string) string {
|
||||
tag = strings.ToLower(tag)
|
||||
switch tag {
|
||||
|
|
|
@ -213,24 +213,32 @@ theme {
|
|||
text-color = @ruiPopupTextColor,
|
||||
radius = 4px,
|
||||
shadow = _{spread-radius=4px, blur=16px, color=#80808080},
|
||||
}
|
||||
},
|
||||
ruiPopupTitle {
|
||||
background-color = @ruiPopupTitleColor,
|
||||
text-color = @ruiPopupTitleTextColor,
|
||||
min-height = 24px,
|
||||
}
|
||||
},
|
||||
ruiMessageText {
|
||||
padding-left = 64px,
|
||||
padding-right = 64px,
|
||||
padding-top = 32px,
|
||||
padding-bottom = 32px,
|
||||
}
|
||||
},
|
||||
ruiPopupMenuItem {
|
||||
padding-top = 4px,
|
||||
padding-bottom = 4px,
|
||||
padding-left = 8px,
|
||||
padding-right = 8px,
|
||||
}
|
||||
},
|
||||
ruiCurrentTableCell {
|
||||
background-color=@ruiSelectedColor,
|
||||
text-color=@ruiSelectedTextColor,
|
||||
},
|
||||
ruiCurrentTableCellFocused {
|
||||
background-color=@ruiHighlightColor,
|
||||
text-color=@ruiHighlightTextColor,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@ GridLayout {
|
|||
DropDownList { row = 5, column = 1, id = tableFootStyle, current = 0, items = ["none", "tableFoot1", "rui.Params"]},
|
||||
Checkbox { row = 6, column = 0:1, id = tableRowStyle, content = "Row style" },
|
||||
Checkbox { row = 7, column = 0:1, id = tableColumnStyle, content = "Column style" },
|
||||
TextView { row = 8, text = "Selection mode" },
|
||||
DropDownList { row = 8, column = 1, id = tableSelectionMode, current = 0, items = ["none", "cell", "row"]},
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -93,6 +95,10 @@ func createTableViewDemo(session rui.Session) rui.View {
|
|||
}
|
||||
}
|
||||
|
||||
rui.Set(view, "tableSelectionMode", rui.DropDownEvent, func(list rui.DropDownList, number int) {
|
||||
rui.Set(view, "demoTableView1", rui.SelectionMode, number)
|
||||
})
|
||||
|
||||
rui.Set(view, "tableCellGap", rui.DropDownEvent, func(list rui.DropDownList, number int) {
|
||||
if number == 0 {
|
||||
rui.Set(view, "demoTableView1", rui.Gap, rui.Px(0))
|
||||
|
|
|
@ -39,6 +39,10 @@ func (list *dropDownListData) Init(session Session) {
|
|||
list.dropDownListener = []func(DropDownList, int){}
|
||||
}
|
||||
|
||||
func (list *dropDownListData) Focusable() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (list *dropDownListData) Remove(tag string) {
|
||||
list.remove(strings.ToLower(tag))
|
||||
}
|
||||
|
|
|
@ -63,6 +63,10 @@ func (edit *editViewData) Init(session Session) {
|
|||
edit.tag = "EditView"
|
||||
}
|
||||
|
||||
func (edit *editViewData) Focusable() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (edit *editViewData) normalizeTag(tag string) string {
|
||||
tag = strings.ToLower(tag)
|
||||
switch tag {
|
||||
|
|
|
@ -89,6 +89,10 @@ func (picker *filePickerData) Init(session Session) {
|
|||
picker.fileSelectedListeners = []func(FilePicker, []FileInfo){}
|
||||
}
|
||||
|
||||
func (picker *filePickerData) Focusable() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (picker *filePickerData) Files() []FileInfo {
|
||||
return picker.files
|
||||
}
|
||||
|
|
|
@ -140,11 +140,9 @@ func getFocusListeners(view View, subviewID string, tag string) []func(View) {
|
|||
}
|
||||
|
||||
func focusEventsHtml(view View, buffer *strings.Builder) {
|
||||
for tag, js := range focusEvents {
|
||||
if value := view.getRaw(tag); value != nil {
|
||||
if listeners, ok := value.([]func(View)); ok && len(listeners) > 0 {
|
||||
buffer.WriteString(js.jsEvent + `="` + js.jsFunc + `(this, event)" `)
|
||||
}
|
||||
if view.Focusable() {
|
||||
for _, js := range focusEvents {
|
||||
buffer.WriteString(js.jsEvent + `="` + js.jsFunc + `(this, event)" `)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
23
listView.go
23
listView.go
|
@ -1083,14 +1083,12 @@ func (listView *listViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
|||
func (listView *listViewData) handleCommand(self View, command string, data DataObject) bool {
|
||||
switch command {
|
||||
case "itemSelected":
|
||||
if text, ok := data.PropertyValue(`number`); ok {
|
||||
if number, err := strconv.Atoi(text); err == nil {
|
||||
listView.properties[Current] = number
|
||||
for _, listener := range listView.selectedListeners {
|
||||
listener(listView, number)
|
||||
}
|
||||
listView.propertyChangedEvent(Current)
|
||||
if number, ok := dataIntProperty(data, `number`); ok {
|
||||
listView.properties[Current] = number
|
||||
for _, listener := range listView.selectedListeners {
|
||||
listener(listView, number)
|
||||
}
|
||||
listView.propertyChangedEvent(Current)
|
||||
}
|
||||
|
||||
case "itemUnselected":
|
||||
|
@ -1162,9 +1160,14 @@ func (listView *listViewData) onItemClick() {
|
|||
}
|
||||
}
|
||||
|
||||
func (listView *listViewData) onItemResize(self View, index int, x, y, width, height float64) {
|
||||
if index >= 0 && index < len(listView.itemFrame) {
|
||||
listView.itemFrame[index] = Frame{Left: x, Top: y, Width: width, Height: height}
|
||||
func (listView *listViewData) onItemResize(self View, index string, x, y, width, height float64) {
|
||||
n, err := strconv.Atoi(index)
|
||||
if err != nil {
|
||||
ErrorLog(err.Error())
|
||||
} else if n >= 0 && n < len(listView.itemFrame) {
|
||||
listView.itemFrame[n] = Frame{Left: x, Top: y, Width: width, Height: height}
|
||||
} else {
|
||||
ErrorLogF(`Invalid ListView item index: %d`, n)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -168,6 +168,10 @@ func (player *mediaPlayerData) Init(session Session) {
|
|||
player.tag = "MediaPlayer"
|
||||
}
|
||||
|
||||
func (player *mediaPlayerData) Focusable() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (player *mediaPlayerData) Remove(tag string) {
|
||||
player.remove(strings.ToLower(tag))
|
||||
}
|
||||
|
|
|
@ -50,6 +50,10 @@ func (picker *numberPickerData) Init(session Session) {
|
|||
picker.numberChangedListeners = []func(NumberPicker, float64){}
|
||||
}
|
||||
|
||||
func (picker *numberPickerData) Focusable() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (picker *numberPickerData) normalizeTag(tag string) string {
|
||||
tag = strings.ToLower(tag)
|
||||
switch tag {
|
||||
|
|
|
@ -18,7 +18,7 @@ func (view *viewData) onResize(self View, x, y, width, height float64) {
|
|||
}
|
||||
}
|
||||
|
||||
func (view *viewData) onItemResize(self View, index int, x, y, width, height float64) {
|
||||
func (view *viewData) onItemResize(self View, index string, x, y, width, height float64) {
|
||||
}
|
||||
|
||||
func (view *viewData) setFrameListener(tag string, value interface{}) bool {
|
||||
|
|
10
session.go
10
session.go
|
@ -378,14 +378,10 @@ func (session *sessionData) handleResize(data DataObject) {
|
|||
}
|
||||
if viewID, ok := obj.PropertyValue("id"); ok {
|
||||
if n := strings.IndexRune(viewID, '-'); n > 0 {
|
||||
if index, err := strconv.Atoi(viewID[n+1:]); err == nil {
|
||||
if view := session.viewByHTMLID(viewID[:n]); view != nil {
|
||||
view.onItemResize(view, index, getFloat("x"), getFloat("y"), getFloat("width"), getFloat("height"))
|
||||
} else {
|
||||
ErrorLogF(`View with id == %s not found`, viewID[:n])
|
||||
}
|
||||
if view := session.viewByHTMLID(viewID[:n]); view != nil {
|
||||
view.onItemResize(view, viewID[n+1:], getFloat("x"), getFloat("y"), getFloat("width"), getFloat("height"))
|
||||
} else {
|
||||
ErrorLogF(`Invalid view id == %s not found`, viewID)
|
||||
ErrorLogF(`View with id == %s not found`, viewID[:n])
|
||||
}
|
||||
} else if view := session.viewByHTMLID(viewID); view != nil {
|
||||
view.onResize(view, getFloat("x"), getFloat("y"), getFloat("width"), getFloat("height"))
|
||||
|
|
344
tableView.go
344
tableView.go
|
@ -214,11 +214,14 @@ type TableView interface {
|
|||
View
|
||||
ParanetView
|
||||
ReloadTableData()
|
||||
CellFrame(row, column int) Frame
|
||||
getCurrent() CellIndex
|
||||
}
|
||||
|
||||
type tableViewData struct {
|
||||
viewData
|
||||
cellViews []View
|
||||
cellFrame []Frame
|
||||
cellSelectedListener, cellClickedListener []func(TableView, int, int)
|
||||
rowSelectedListener, rowClickedListener []func(TableView, int)
|
||||
current CellIndex
|
||||
|
@ -245,6 +248,7 @@ func (table *tableViewData) Init(session Session) {
|
|||
table.viewData.Init(session)
|
||||
table.tag = "TableView"
|
||||
table.cellViews = []View{}
|
||||
table.cellFrame = []Frame{}
|
||||
table.cellSelectedListener = []func(TableView, int, int){}
|
||||
table.cellClickedListener = []func(TableView, int, int){}
|
||||
table.rowSelectedListener = []func(TableView, int){}
|
||||
|
@ -270,6 +274,10 @@ func (table *tableViewData) normalizeTag(tag string) string {
|
|||
return tag
|
||||
}
|
||||
|
||||
func (table *tableViewData) Focusable() bool {
|
||||
return GetSelectionMode(table, "") != NoneSelection
|
||||
}
|
||||
|
||||
func (table *tableViewData) Get(tag string) interface{} {
|
||||
return table.get(table.normalizeTag(tag))
|
||||
}
|
||||
|
@ -312,6 +320,10 @@ func (table *tableViewData) remove(tag string) {
|
|||
table.current.Column = -1
|
||||
table.propertyChanged(tag)
|
||||
|
||||
case SelectionMode:
|
||||
table.viewData.remove(tag)
|
||||
table.propertyChanged(tag)
|
||||
|
||||
default:
|
||||
table.viewData.remove(tag)
|
||||
}
|
||||
|
@ -486,14 +498,51 @@ func (table *tableViewData) set(tag string, value interface{}) bool {
|
|||
}
|
||||
|
||||
case Current:
|
||||
switch GetSelectionMode(table, "") {
|
||||
case NoneSelection:
|
||||
switch value := value.(type) {
|
||||
case int:
|
||||
table.current.Row = value
|
||||
table.current.Column = -1
|
||||
|
||||
case CellSelection:
|
||||
// TODO
|
||||
case CellIndex:
|
||||
table.current = value
|
||||
|
||||
case RowSelection:
|
||||
// TODO
|
||||
case DataObject:
|
||||
if row, ok := dataIntProperty(value, "row"); ok {
|
||||
table.current.Row = row
|
||||
}
|
||||
if column, ok := dataIntProperty(value, "column"); ok {
|
||||
table.current.Column = column
|
||||
}
|
||||
|
||||
case string:
|
||||
if strings.Contains(value, ",") {
|
||||
if values := strings.Split(value, ","); len(values) == 2 {
|
||||
var n = []int{0, 0}
|
||||
for i := 0; i < 2; i++ {
|
||||
var err error
|
||||
if n[i], err = strconv.Atoi(values[i]); err != nil {
|
||||
ErrorLog(err.Error())
|
||||
return false
|
||||
}
|
||||
}
|
||||
table.current.Row = n[0]
|
||||
table.current.Column = n[1]
|
||||
} else {
|
||||
notCompatibleType(tag, value)
|
||||
}
|
||||
} else {
|
||||
n, err := strconv.Atoi(value)
|
||||
if err != nil {
|
||||
ErrorLog(err.Error())
|
||||
return false
|
||||
}
|
||||
table.current.Row = n
|
||||
table.current.Column = -1
|
||||
}
|
||||
|
||||
default:
|
||||
notCompatibleType(tag, value)
|
||||
return false
|
||||
}
|
||||
|
||||
default:
|
||||
|
@ -524,11 +573,75 @@ func (table *tableViewData) propertyChanged(tag string) {
|
|||
updateCSSProperty(htmlID, "border-spacing", gap.cssString("0"), session)
|
||||
updateCSSProperty(htmlID, "border-collapse", "separate", session)
|
||||
}
|
||||
|
||||
case SelectionMode:
|
||||
htmlID := table.htmlID()
|
||||
session := table.Session()
|
||||
|
||||
switch GetSelectionMode(table, "") {
|
||||
case CellSelection:
|
||||
updateProperty(htmlID, "tabindex", "0", session)
|
||||
updateProperty(htmlID, "onfocus", "tableViewFocusEvent(this, event)", session)
|
||||
updateProperty(htmlID, "onblur", "tableViewBlurEvent(this, event)", session)
|
||||
updateProperty(htmlID, "data-selection", "cell", session)
|
||||
updateProperty(htmlID, "data-focusitemstyle", table.currentStyle(), session)
|
||||
updateProperty(htmlID, "data-bluritemstyle", table.currentInactiveStyle(), session)
|
||||
|
||||
if table.current.Row >= 0 && table.current.Column >= 0 {
|
||||
updateProperty(htmlID, "data-current", table.cellID(table.current.Row, table.current.Column), session)
|
||||
} else {
|
||||
removeProperty(htmlID, "data-current", session)
|
||||
}
|
||||
updateProperty(htmlID, "onkeydown", "tableViewCellKeyDownEvent(this, event)", session)
|
||||
|
||||
case RowSelection:
|
||||
updateProperty(htmlID, "tabindex", "0", session)
|
||||
updateProperty(htmlID, "onfocus", "tableViewFocusEvent(this, event)", session)
|
||||
updateProperty(htmlID, "onblur", "tableViewBlurEvent(this, event)", session)
|
||||
updateProperty(htmlID, "data-selection", "cell", session)
|
||||
updateProperty(htmlID, "data-focusitemstyle", table.currentStyle(), session)
|
||||
updateProperty(htmlID, "data-bluritemstyle", table.currentInactiveStyle(), session)
|
||||
|
||||
if table.current.Row >= 0 {
|
||||
updateProperty(htmlID, "data-current", table.rowID(table.current.Row), session)
|
||||
} else {
|
||||
removeProperty(htmlID, "data-current", session)
|
||||
}
|
||||
updateProperty(htmlID, "onkeydown", "tableViewRowKeyDownEvent(this, event)", session)
|
||||
|
||||
default: // NoneSelection
|
||||
for _, prop := range []string{"tabindex", "data-current", "onfocus", "onblur", "onkeydown", "data-selection"} {
|
||||
removeProperty(htmlID, prop, session)
|
||||
}
|
||||
}
|
||||
updateInnerHTML(htmlID, session)
|
||||
}
|
||||
}
|
||||
table.propertyChangedEvent(tag)
|
||||
}
|
||||
|
||||
func (table *tableViewData) currentStyle() string {
|
||||
if value := table.getRaw(CurrentStyle); value != nil {
|
||||
if style, ok := value.(string); ok {
|
||||
if style, ok = table.session.resolveConstants(style); ok {
|
||||
return style
|
||||
}
|
||||
}
|
||||
}
|
||||
return "ruiCurrentTableCellFocused"
|
||||
}
|
||||
|
||||
func (table *tableViewData) currentInactiveStyle() string {
|
||||
if value := table.getRaw(CurrentInactiveStyle); value != nil {
|
||||
if style, ok := value.(string); ok {
|
||||
if style, ok = table.session.resolveConstants(style); ok {
|
||||
return style
|
||||
}
|
||||
}
|
||||
}
|
||||
return "ruiCurrentTableCell"
|
||||
}
|
||||
|
||||
func (table *tableViewData) valueToCellListeners(value interface{}) []func(TableView, int, int) {
|
||||
if value == nil {
|
||||
return []func(TableView, int, int){}
|
||||
|
@ -643,16 +756,69 @@ func (table *tableViewData) htmlTag() string {
|
|||
return "table"
|
||||
}
|
||||
|
||||
func (table *tableViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
||||
table.cellViews = []View{}
|
||||
func (table *tableViewData) rowID(index int) string {
|
||||
return fmt.Sprintf("%s-%d", table.htmlID(), index)
|
||||
}
|
||||
|
||||
content := table.getRaw(Content)
|
||||
if content == nil {
|
||||
return
|
||||
func (table *tableViewData) cellID(row, column int) string {
|
||||
return fmt.Sprintf("%s-%d-%d", table.htmlID(), row, column)
|
||||
}
|
||||
|
||||
func (table *tableViewData) htmlProperties(self View, buffer *strings.Builder) {
|
||||
|
||||
if content := table.content(); content != nil {
|
||||
buffer.WriteString(` data-rows="`)
|
||||
buffer.WriteString(strconv.Itoa(content.RowCount()))
|
||||
buffer.WriteString(`" data-columns="`)
|
||||
buffer.WriteString(strconv.Itoa(content.ColumnCount()))
|
||||
buffer.WriteRune('"')
|
||||
}
|
||||
|
||||
adapter, ok := content.(TableAdapter)
|
||||
if !ok {
|
||||
if selectionMode := GetSelectionMode(table, ""); selectionMode != NoneSelection {
|
||||
buffer.WriteString(` onfocus="tableViewFocusEvent(this, event)" onblur="tableViewBlurEvent(this, event)" data-focusitemstyle="`)
|
||||
buffer.WriteString(table.currentStyle())
|
||||
buffer.WriteString(`" data-bluritemstyle="`)
|
||||
buffer.WriteString(table.currentInactiveStyle())
|
||||
buffer.WriteRune('"')
|
||||
|
||||
switch selectionMode {
|
||||
case RowSelection:
|
||||
buffer.WriteString(` data-selection="row" onkeydown="tableViewRowKeyDownEvent(this, event)"`)
|
||||
if table.current.Row >= 0 {
|
||||
buffer.WriteString(` data-current="`)
|
||||
buffer.WriteString(table.rowID(table.current.Row))
|
||||
buffer.WriteRune('"')
|
||||
}
|
||||
|
||||
case CellSelection:
|
||||
buffer.WriteString(` data-selection="cell" onkeydown="tableViewCellKeyDownEvent(this, event)"`)
|
||||
if table.current.Row >= 0 && table.current.Column >= 0 {
|
||||
buffer.WriteString(` data-current="`)
|
||||
buffer.WriteString(table.cellID(table.current.Row, table.current.Column))
|
||||
buffer.WriteRune('"')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
table.viewData.htmlProperties(self, buffer)
|
||||
}
|
||||
|
||||
func (table *tableViewData) content() TableAdapter {
|
||||
if content := table.getRaw(Content); content != nil {
|
||||
if adapter, ok := content.(TableAdapter); ok {
|
||||
return adapter
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (table *tableViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
||||
table.cellViews = []View{}
|
||||
table.cellFrame = []Frame{}
|
||||
|
||||
adapter := table.content()
|
||||
if adapter == nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -662,10 +828,12 @@ func (table *tableViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
|||
return
|
||||
}
|
||||
|
||||
table.cellFrame = make([]Frame, rowCount*columnCount)
|
||||
|
||||
rowStyle := table.getRowStyle()
|
||||
|
||||
var cellStyle1 TableCellStyle = nil
|
||||
if style, ok := content.(TableCellStyle); ok {
|
||||
if style, ok := adapter.(TableCellStyle); ok {
|
||||
cellStyle1 = style
|
||||
}
|
||||
|
||||
|
@ -691,6 +859,7 @@ func (table *tableViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
|||
view.Init(session)
|
||||
|
||||
ignorCells := []struct{ row, column int }{}
|
||||
selectionMode := GetSelectionMode(table, "")
|
||||
|
||||
tableCSS := func(startRow, endRow int, cellTag string, cellBorder BorderProperty, cellPadding BoundsProperty) {
|
||||
for row := startRow; row < endRow; row++ {
|
||||
|
@ -706,14 +875,31 @@ func (table *tableViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
|||
}
|
||||
}
|
||||
|
||||
if cssBuilder.buffer.Len() > 0 {
|
||||
buffer.WriteString(`<tr style="`)
|
||||
buffer.WriteString(cssBuilder.buffer.String())
|
||||
buffer.WriteString(`">`)
|
||||
} else {
|
||||
buffer.WriteString("<tr>")
|
||||
buffer.WriteString(`<tr id="`)
|
||||
buffer.WriteString(table.rowID(row))
|
||||
buffer.WriteRune('"')
|
||||
|
||||
if selectionMode == RowSelection {
|
||||
if row == table.current.Row {
|
||||
buffer.WriteString(` class="`)
|
||||
if table.HasFocus() {
|
||||
buffer.WriteString(table.currentStyle())
|
||||
} else {
|
||||
buffer.WriteString(table.currentInactiveStyle())
|
||||
}
|
||||
buffer.WriteRune('"')
|
||||
}
|
||||
|
||||
buffer.WriteString(` onclick="tableRowClickEvent(this, event)"`)
|
||||
}
|
||||
|
||||
if cssBuilder.buffer.Len() > 0 {
|
||||
buffer.WriteString(` style="`)
|
||||
buffer.WriteString(cssBuilder.buffer.String())
|
||||
buffer.WriteString(`"`)
|
||||
}
|
||||
buffer.WriteString(">")
|
||||
|
||||
for column := 0; column < columnCount; column++ {
|
||||
ignore := false
|
||||
for _, cell := range ignorCells {
|
||||
|
@ -748,7 +934,7 @@ func (table *tableViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
|||
return value
|
||||
|
||||
case string:
|
||||
if value, ok = session.resolveConstants(value); ok {
|
||||
if value, ok := session.resolveConstants(value); ok {
|
||||
if n, err := strconv.Atoi(value); err == nil {
|
||||
return n
|
||||
}
|
||||
|
@ -780,6 +966,23 @@ func (table *tableViewData) htmlSubviews(self View, buffer *strings.Builder) {
|
|||
|
||||
buffer.WriteRune('<')
|
||||
buffer.WriteString(cellTag)
|
||||
buffer.WriteString(` id="`)
|
||||
buffer.WriteString(table.cellID(row, column))
|
||||
buffer.WriteString(`" class="ruiView`)
|
||||
|
||||
if selectionMode == CellSelection && row == table.current.Row && column == table.current.Column {
|
||||
buffer.WriteRune(' ')
|
||||
if table.HasFocus() {
|
||||
buffer.WriteString(table.currentStyle())
|
||||
} else {
|
||||
buffer.WriteString(table.currentInactiveStyle())
|
||||
}
|
||||
}
|
||||
buffer.WriteRune('"')
|
||||
|
||||
if selectionMode == CellSelection {
|
||||
buffer.WriteString(` onclick="tableCellClickEvent(this, event)"`)
|
||||
}
|
||||
|
||||
if columnSpan > 1 {
|
||||
buffer.WriteString(` colspan="`)
|
||||
|
@ -1087,6 +1290,10 @@ func (table *tableViewData) getCellBorder() BorderProperty {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (table *tableViewData) getCurrent() CellIndex {
|
||||
return table.current
|
||||
}
|
||||
|
||||
func (table *tableViewData) cssStyle(self View, builder cssBuilder) {
|
||||
table.viewData.cssViewStyle(builder, table.Session())
|
||||
|
||||
|
@ -1101,30 +1308,93 @@ func (table *tableViewData) cssStyle(self View, builder cssBuilder) {
|
|||
}
|
||||
|
||||
func (table *tableViewData) ReloadTableData() {
|
||||
if content := table.content(); content != nil {
|
||||
updateProperty(table.htmlID(), "data-rows", strconv.Itoa(content.RowCount()), table.Session())
|
||||
updateProperty(table.htmlID(), "data-columns", strconv.Itoa(content.ColumnCount()), table.Session())
|
||||
}
|
||||
updateInnerHTML(table.htmlID(), table.Session())
|
||||
}
|
||||
|
||||
func (cell *tableCellView) Set(tag string, value interface{}) bool {
|
||||
return cell.set(strings.ToLower(tag), value)
|
||||
func (table *tableViewData) onItemResize(self View, index string, x, y, width, height float64) {
|
||||
if n := strings.IndexRune(index, '-'); n > 0 {
|
||||
if row, err := strconv.Atoi(index[:n]); err == nil {
|
||||
if column, err := strconv.Atoi(index[n+1:]); err == nil {
|
||||
if content := table.content(); content != nil {
|
||||
i := row*content.ColumnCount() + column
|
||||
if i < len(table.cellFrame) {
|
||||
table.cellFrame[i].Left = x
|
||||
table.cellFrame[i].Top = y
|
||||
table.cellFrame[i].Width = width
|
||||
table.cellFrame[i].Height = height
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ErrorLog(err.Error())
|
||||
}
|
||||
} else {
|
||||
ErrorLog(err.Error())
|
||||
}
|
||||
} else {
|
||||
ErrorLogF(`Invalid cell index: %s`, index)
|
||||
}
|
||||
}
|
||||
|
||||
func (cell *tableCellView) set(tag string, value interface{}) bool {
|
||||
switch tag {
|
||||
case VerticalAlign:
|
||||
tag = TableVerticalAlign
|
||||
}
|
||||
return cell.viewData.set(tag, value)
|
||||
}
|
||||
|
||||
func (cell *tableCellView) cssStyle(self View, builder cssBuilder) {
|
||||
session := cell.Session()
|
||||
cell.viewData.cssViewStyle(builder, session)
|
||||
|
||||
if value, ok := enumProperty(cell, TableVerticalAlign, session, 0); ok {
|
||||
builder.add("vertical-align", enumProperties[TableVerticalAlign].values[value])
|
||||
func (table *tableViewData) CellFrame(row, column int) Frame {
|
||||
if content := table.content(); content != nil {
|
||||
i := row*content.ColumnCount() + column
|
||||
if i < len(table.cellFrame) {
|
||||
return table.cellFrame[i]
|
||||
}
|
||||
}
|
||||
return Frame{}
|
||||
}
|
||||
|
||||
func (table *tableViewData) Views() []View {
|
||||
return table.cellViews
|
||||
}
|
||||
|
||||
func (table *tableViewData) handleCommand(self View, command string, data DataObject) bool {
|
||||
switch command {
|
||||
case "currentRow":
|
||||
if row, ok := dataIntProperty(data, "row"); ok && row != table.current.Row {
|
||||
table.current.Row = row
|
||||
for _, listener := range table.rowSelectedListener {
|
||||
listener(table, row)
|
||||
}
|
||||
}
|
||||
|
||||
case "currentCell":
|
||||
if row, ok := dataIntProperty(data, "row"); ok {
|
||||
if column, ok := dataIntProperty(data, "column"); ok {
|
||||
if row != table.current.Row || column != table.current.Column {
|
||||
table.current.Row = row
|
||||
table.current.Column = column
|
||||
for _, listener := range table.cellSelectedListener {
|
||||
listener(table, row, column)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case "rowClick":
|
||||
if row, ok := dataIntProperty(data, "row"); ok {
|
||||
for _, listener := range table.rowClickedListener {
|
||||
listener(table, row)
|
||||
}
|
||||
}
|
||||
|
||||
case "cellClick":
|
||||
if row, ok := dataIntProperty(data, "row"); ok {
|
||||
if column, ok := dataIntProperty(data, "column"); ok {
|
||||
for _, listener := range table.cellClickedListener {
|
||||
listener(table, row, column)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return table.viewData.handleCommand(self, command, data)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -1,5 +1,28 @@
|
|||
package rui
|
||||
|
||||
import "strings"
|
||||
|
||||
func (cell *tableCellView) Set(tag string, value interface{}) bool {
|
||||
return cell.set(strings.ToLower(tag), value)
|
||||
}
|
||||
|
||||
func (cell *tableCellView) set(tag string, value interface{}) bool {
|
||||
switch tag {
|
||||
case VerticalAlign:
|
||||
tag = TableVerticalAlign
|
||||
}
|
||||
return cell.viewData.set(tag, value)
|
||||
}
|
||||
|
||||
func (cell *tableCellView) cssStyle(self View, builder cssBuilder) {
|
||||
session := cell.Session()
|
||||
cell.viewData.cssViewStyle(builder, session)
|
||||
|
||||
if value, ok := enumProperty(cell, TableVerticalAlign, session, 0); ok {
|
||||
builder.add("vertical-align", enumProperties[TableVerticalAlign].values[value])
|
||||
}
|
||||
}
|
||||
|
||||
// GetSelectionMode returns the mode of the TableView elements selection.
|
||||
// Valid values are NoneSelection (0), CellSelection (1), and RowSelection (2).
|
||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
||||
|
@ -15,6 +38,42 @@ func GetSelectionMode(view View, subviewID string) int {
|
|||
return NoneSelection
|
||||
}
|
||||
|
||||
// GetSelectionMode returns the index of the TableView selected row.
|
||||
// If there is no selected row, then a value less than 0 are returned.
|
||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
||||
func GetCurrentTableRow(view View, subviewID string) int {
|
||||
if subviewID != "" {
|
||||
view = ViewByID(view, subviewID)
|
||||
}
|
||||
|
||||
if view != nil {
|
||||
if selectionMode := GetSelectionMode(view, ""); selectionMode != NoneSelection {
|
||||
if tableView, ok := view.(TableView); ok {
|
||||
return tableView.getCurrent().Row
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// GetCurrentTableCell returns the row and column index of the TableView selected cell.
|
||||
// If there is no selected cell, then a value of the row and column index less than 0 is returned.
|
||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
||||
func GetCurrentTableCell(view View, subviewID string) CellIndex {
|
||||
if subviewID != "" {
|
||||
view = ViewByID(view, subviewID)
|
||||
}
|
||||
|
||||
if view != nil {
|
||||
if selectionMode := GetSelectionMode(view, ""); selectionMode != NoneSelection {
|
||||
if tableView, ok := view.(TableView); ok {
|
||||
return tableView.getCurrent()
|
||||
}
|
||||
}
|
||||
}
|
||||
return CellIndex{Row: -1, Column: -1}
|
||||
}
|
||||
|
||||
// GetTableCellClickedListeners returns listeners of event which occurs when the user clicks on a table cell.
|
||||
// If there are no listeners then the empty list is returned.
|
||||
// If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
|
||||
|
|
|
@ -44,6 +44,10 @@ func (picker *timePickerData) Init(session Session) {
|
|||
picker.timeChangedListeners = []func(TimePicker, time.Time){}
|
||||
}
|
||||
|
||||
func (picker *timePickerData) Focusable() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (picker *timePickerData) normalizeTag(tag string) string {
|
||||
tag = strings.ToLower(tag)
|
||||
switch tag {
|
||||
|
|
18
view.go
18
view.go
|
@ -58,6 +58,8 @@ type View interface {
|
|||
SetAnimated(tag string, value interface{}, animation Animation) bool
|
||||
// SetChangeListener set the function to track the change of the View property
|
||||
SetChangeListener(tag string, listener func(View, string))
|
||||
// HasFocus returns 'true' if the view has focus
|
||||
HasFocus() bool
|
||||
|
||||
handleCommand(self View, command string, data DataObject) bool
|
||||
htmlClass(disabled bool) string
|
||||
|
@ -73,7 +75,7 @@ type View interface {
|
|||
getTransitions() Params
|
||||
|
||||
onResize(self View, x, y, width, height float64)
|
||||
onItemResize(self View, index int, x, y, width, height float64)
|
||||
onItemResize(self View, index string, x, y, width, height float64)
|
||||
setNoResizeEvent()
|
||||
isNoResizeEvent() bool
|
||||
setScroll(x, y, width, height float64)
|
||||
|
@ -95,6 +97,7 @@ type viewData struct {
|
|||
scroll Frame
|
||||
noResizeEvent bool
|
||||
created bool
|
||||
hasFocus bool
|
||||
//animation map[string]AnimationEndListener
|
||||
}
|
||||
|
||||
|
@ -737,7 +740,14 @@ func (view *viewData) handleCommand(self View, command string, data DataObject)
|
|||
case TouchStart, TouchEnd, TouchMove, TouchCancel:
|
||||
handleTouchEvents(self, command, data)
|
||||
|
||||
case FocusEvent, LostFocusEvent:
|
||||
case FocusEvent:
|
||||
view.hasFocus = true
|
||||
for _, listener := range getFocusListeners(view, "", command) {
|
||||
listener(self)
|
||||
}
|
||||
|
||||
case LostFocusEvent:
|
||||
view.hasFocus = false
|
||||
for _, listener := range getFocusListeners(view, "", command) {
|
||||
listener(self)
|
||||
}
|
||||
|
@ -838,3 +848,7 @@ func (view *viewData) SetChangeListener(tag string, listener func(View, string))
|
|||
view.changeListener[tag] = listener
|
||||
}
|
||||
}
|
||||
|
||||
func (view *viewData) HasFocus() bool {
|
||||
return view.hasFocus
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue