Skip to content

Commit

Permalink
feat(MD-3347): copy cell in table (ios) (#94)
Browse files Browse the repository at this point in the history
Co-authored-by: Vittorio Cellucci <vel@qlik.com>
  • Loading branch information
vcellu and vcellu committed Oct 25, 2022
1 parent 31b2be7 commit a071134
Show file tree
Hide file tree
Showing 31 changed files with 927 additions and 98 deletions.
1 change: 1 addition & 0 deletions ios/ColorParser.swift
Expand Up @@ -23,6 +23,7 @@ class ColorParser {
"lightgrey": .lightGray,
"darkgrey": .darkGray,
"purple": .purple,
"orange": .orange,
"teal": .systemTeal]

func fromCSS(cssString: String) -> UIColor {
Expand Down
5 changes: 4 additions & 1 deletion ios/ColumnWidths.swift
Expand Up @@ -74,10 +74,13 @@ class ColumnWidths {
}

fileprivate func getAverageWidth(dataRows: [DataRow], index: Int) -> Double {
if dataRows.count == 0 {
return DataCellView.minWidth
}
let totalCount = dataRows.reduce(0) { partialResult, row in
return partialResult + row.cells[index].qText!.count
}
let average = totalCount / dataRows.count
let average = totalCount / (dataRows.count)
let tempLabel = UILabel()
tempLabel.font = tempLabel.font.withSize(16)
tempLabel.text = String(repeating: "M", count: average)
Expand Down
23 changes: 23 additions & 0 deletions ios/ContainerView.swift
Expand Up @@ -19,6 +19,7 @@ class ContainerView: UIView {
var cellStyle: CellContentStyle?
var headerStyle: HeaderContentStyle?
var defaultCalculated = false
var menuTranslations: MenuTranslations?
var columnWidths = ColumnWidths()
var grabbers = [() -> GrabberView?]()
weak var mainHeaderView: HeaderView?
Expand All @@ -37,6 +38,8 @@ class ContainerView: UIView {
@objc var onEndReached: RCTDirectEventBlock?
@objc var onVerticalScrollEnded: RCTDirectEventBlock?
@objc var onHeaderPressed: RCTDirectEventBlock?
@objc var onExpandCell: RCTDirectEventBlock?
@objc var onSearchColumn: RCTDirectEventBlock?
@objc var containerWidth: NSNumber?
@objc var freezeFirstColumn: Bool = false
@objc var isDataView: Bool = false
Expand Down Expand Up @@ -202,6 +205,18 @@ class ContainerView: UIView {
}
}

@objc var translations: NSDictionary = [:] {
didSet {
do {
let json = try JSONSerialization.data(withJSONObject: translations)
let decodedTranslations = try JSONDecoder().decode(Translations.self, from: json)
menuTranslations = decodedTranslations.menu
} catch {
print(error)
}
}
}

override var bounds: CGRect {
didSet {
guard let dataRows = dataRows else {
Expand Down Expand Up @@ -360,6 +375,7 @@ class ContainerView: UIView {
columns: dataColumns,
withTheme: tableTheme!,
onHeaderPressed: onHeaderPressed,
onSearchColumn: onSearchColumn,
headerStyle: headerStyle!,
columnWidths: columnWidths,
withRange: 0..<1)
Expand All @@ -379,6 +395,7 @@ class ContainerView: UIView {
columns: dataColumns,
withTheme: tableTheme!,
onHeaderPressed: onHeaderPressed,
onSearchColumn: onSearchColumn,
headerStyle: headerStyle!,
columnWidths: columnWidths,
withRange: 1..<columnWidths.count())
Expand Down Expand Up @@ -495,6 +512,8 @@ class ContainerView: UIView {
dataCollectionView.headerView = self.primaryHeaderView
dataCollectionView.totalsView = self.primaryTotalsView
dataCollectionView.freezeFirstColumn = self.freezeFirstColumn
dataCollectionView.menuTranslations = self.menuTranslations
dataCollectionView.onExpandedCell = self.onExpandCell
hScrollViewDelegate.collectionView = dataCollectionView

if let masterHeaderView = primaryHeaderView {
Expand Down Expand Up @@ -530,7 +549,9 @@ class ContainerView: UIView {
collectionView.headerView = self.secondaryHeaderView
collectionView.totalsView = self.secondaryTotalsView
collectionView.freezeFirstColumn = self.freezeFirstColumn
collectionView.menuTranslations = self.menuTranslations
collectionView.hScrollView = scrollView
collectionView.onExpandedCell = self.onExpandCell
collectionView.backgroundColor = .red

scrollView.addSubview(collectionView)
Expand Down Expand Up @@ -714,4 +735,6 @@ class ContainerView: UIView {
}
}
}


}
55 changes: 55 additions & 0 deletions ios/ContextMenu.swift
@@ -0,0 +1,55 @@
//
// ContextMenu.swift
// react-native-simple-grid
//
// Created by Vittorio Cellucci on 2022-10-21.
//

import Foundation

class ContextMenu: NSObject {
var cell: DataCell?
var menuTranslations: MenuTranslations?

func showMenu(_ sender: UILongPressGestureRecognizer, view: UIView) {
guard let menuTranslations = self.menuTranslations else {return}
view.becomeFirstResponder()

let menu = UIMenuController.shared

let locationOfTouchInLabel = sender.location(in: view)

if !menu.isMenuVisible {
var rect = view.bounds
rect.origin = locationOfTouchInLabel
rect.size = CGSize(width: 1, height: 1)

menu.menuItems = [
UIMenuItem(
title: menuTranslations.copy ?? "Copy",
action: #selector(handleCopy(_:))
),
UIMenuItem(
title: menuTranslations.expand ?? "Expand Row",
action: #selector(handleExpand(_:))

)
]

menu.setTargetRect(view.frame, in: view)

if #available(iOS 13.0, *) {
menu.showMenu(from: view, rect: rect)
} else {
// Fallback on earlier versions
}
}
}

@objc func handleCopy(_ controller: UIMenuController) {
}

@objc func handleExpand(_ controller: UIMenuController) {
}

}
45 changes: 40 additions & 5 deletions ios/DataCellView.swift
Expand Up @@ -40,14 +40,17 @@ func isDarkColor(color: UIColor) -> Bool {
{ key: 'minus-2', value: 'lui-icon--minus-2' },
{ key: 'dot', value: 'lui-icon--dot' },
*/
class DataCellView: UICollectionViewCell {
class DataCellView: UICollectionViewCell, ExpandedCellProtocol {
var border = UIBezierPath()
var dataRow: DataRow?
var dataColumns: [DataColumn]?
var borderColor = UIColor.black.withAlphaComponent(0.1)
var selectionsEngine: SelectionsEngine?
var cellColor: UIColor?
var numberOfLines = 1
var isDataView = true
var onExpandedCellEvent: RCTDirectEventBlock?
var menuTranslations: MenuTranslations?
weak var selectionBand: SelectionBand?
weak var dataCollectionView: DataCollectionView?

Expand Down Expand Up @@ -82,12 +85,14 @@ class DataCellView: UICollectionViewCell {

func setData(row: DataRow,
withColumns cols: ArraySlice<DataColumn>,
dataColumns: [DataColumn],
columnWidths: [Double],
theme: TableTheme,
selectionsEngine: SelectionsEngine,
withStyle styleInfo: StylingInfo,
withStyle styleInfo: [StylingInfo],
withRange dataRange: CountableRange<Int>) {
dataRow = row
self.dataColumns = dataColumns
borderColor = ColorParser().fromCSS(cssString: theme.borderBackgroundColor ?? "#F0F0F0")
createCells(row: row, withColumns: cols, columnWidths: columnWidths, withRange: dataRange)
var x = 0.0
Expand All @@ -100,7 +105,10 @@ class DataCellView: UICollectionViewCell {
if representation.type == "miniChart" && !isDataView {
if let miniChart = views[index] as? MiniChartView {
miniChart.frame = newFrame.integral
miniChart.menuTranslations = menuTranslations
miniChart.cell = element
miniChart.setChartData(data: element, representedAs: representation)
miniChart.delegate = self
miniChart.setNeedsDisplay()
}
} else if representation.type == "image" && !isDataView {
Expand All @@ -114,21 +122,23 @@ class DataCellView: UICollectionViewCell {
label.textAlignment = element.qNum == nil ? .left : .right
label.frame = newFrame.integral
label.center = CGPoint(x: floor(label.center.x), y: floor(label.center.y))
let backgroundColor = getBackgroundColor(col: col, element: element, withStyle: styleInfo)
let backgroundColor = getBackgroundColor(col: col, element: element, withStyle: styleInfo[index])
label.backgroundColor = backgroundColor
label.numberOfLines = numberOfLines
label.column = index
label.cell = element
label.checkSelected(selectionsEngine)
label.selectionBand = self.selectionBand
label.dataCollectionView = self.dataCollectionView
label.menuTranslations = self.menuTranslations
label.delegate = self

label.checkForUrls()
if representation.type == "indicator", let indicator = element.indicator, let uniChar = DataCellView.iconMap[indicator.icon ?? "m"] {
label.setAttributedText(element.qText ?? "", withIcon: uniChar, element: element)
} else {
label.text = element.qText
label.textColor = isDarkColor(color: backgroundColor) ? .white : getForgroundColor(col: col, element: element, withStyle: styleInfo)
label.textColor = isDarkColor(color: backgroundColor) ? .white : getForgroundColor(col: col, element: element, withStyle: styleInfo[index])
}
}
}
Expand All @@ -141,8 +151,12 @@ class DataCellView: UICollectionViewCell {
if isDataView {
return .clear
}
if (styleInfo.backgroundColorIdx == -1) {
return .clear
}
guard let attributes = element.qAttrExps else {return .clear}
guard let values = attributes.qValues else {return .clear}

let colorString = values[styleInfo.backgroundColorIdx].qText ?? "none"
let colorValue = ColorParser().fromCSS(cssString: colorString.lowercased())
return colorValue
Expand All @@ -152,6 +166,9 @@ class DataCellView: UICollectionViewCell {
if isDataView {
return cellColor!
}
if (styleInfo.foregroundColorIdx == -1) {
return cellColor!
}
guard let attributes = element.qAttrExps else {return cellColor!}
guard let values = attributes.qValues else {return cellColor!}
if let qText = values[styleInfo.foregroundColorIdx].qText {
Expand All @@ -176,7 +193,7 @@ class DataCellView: UICollectionViewCell {
let imageCell = ImageCell(frame: .zero)
contentView.addSubview(imageCell)
} else {
let label = PaddedLabel(frame: .zero)
let label = PaddedLabel(frame: .zero, selectionBand: self.selectionBand)
if col.isDim == true {
if let selectionsEngine = selectionsEngine {
label.makeSelectable(selectionsEngine: selectionsEngine)
Expand All @@ -185,6 +202,7 @@ class DataCellView: UICollectionViewCell {
let sizedFont = UIFont.systemFont(ofSize: 14)
label.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: sizedFont)
label.adjustsFontForContentSizeCategory = true
label.showMenus()
contentView.addSubview(label)
}
}
Expand Down Expand Up @@ -281,4 +299,21 @@ class DataCellView: UICollectionViewCell {
border.stroke()

}

func onExpandedCell(cell: DataCell) {
guard let dataRow = self.dataRow else { return }
guard let dataCols = self.dataColumns else { return }
guard let expandedCellEvent = self.onExpandedCellEvent else { return }
do {
let jsonEncoder = JSONEncoder()
let jsonData = try jsonEncoder.encode(dataRow)
let jsonCol = try jsonEncoder.encode(dataCols)
let row = String(data: jsonData, encoding: String.Encoding.utf8)
let col = String(data: jsonCol, encoding: String.Encoding.utf8)
expandedCellEvent(["row": row ?? "", "col": col ?? ""])
} catch {
print(error)
}
}
}

25 changes: 17 additions & 8 deletions ios/DataCollectionView.swift
Expand Up @@ -12,12 +12,13 @@ class DataCollectionView: UIView, UICollectionViewDataSource, UICollectionViewDe
case noCellForIdentifier
}

var stylingInfo = StylingInfo()
var stylingInfo = [StylingInfo]()
var dataColumns: [DataColumn]?
var dataRows: [DataRow]?
var dataSize: DataSize?
var loading = false
var onEndReached: RCTDirectEventBlock?
var onExpandedCell: RCTDirectEventBlock?
var childCollectionView: UICollectionView?
var tableTheme: TableTheme?
var selectionsEngine: SelectionsEngine?
Expand All @@ -27,6 +28,7 @@ class DataCollectionView: UIView, UICollectionViewDataSource, UICollectionViewDe
var isDataView = false
var dataRange: CountableRange = 0..<2
var freezeFirstColumn = false
var menuTranslations: MenuTranslations?
var grabbers: [() -> GrabberView?]?
private var lasso = false
weak var totalCellsView: TotalCellsView?
Expand Down Expand Up @@ -78,9 +80,11 @@ class DataCollectionView: UIView, UICollectionViewDataSource, UICollectionViewDe
guard let childCollectionView = childCollectionView else { return }

let selectionBand = SelectionBand(frame: self.frame)
selectionBand.parentCollectionView = self
childCollectionView.addSubview(selectionBand)
self.selectionBand = selectionBand
if let selectionsEngine = self.selectionsEngine {
selectionsEngine.setSelectionBand(selectionBand);
}

}

Expand Down Expand Up @@ -176,18 +180,20 @@ class DataCollectionView: UIView, UICollectionViewDataSource, UICollectionViewDe
guard let dataColumns = dataColumns else {
return
}

for col in dataColumns[dataRange] {
if let stylingInfo = col.stylingInfo {
var index = 0
self.stylingInfo = [StylingInfo]()
dataColumns[dataRange].enumerated().forEach {(index, element) in
if let stylingInfo = element.stylingInfo {
var index = 0;
var si = StylingInfo()
for style in stylingInfo {
if style == "cellBackgroundColor" {
self.stylingInfo.backgroundColorIdx = index
si.backgroundColorIdx = index
} else if style == "cellForegroundColor" {
self.stylingInfo.foregroundColorIdx = index
si.foregroundColorIdx = index
}
index += 1
}
self.stylingInfo.append(si)
}
}
}
Expand All @@ -206,14 +212,17 @@ class DataCollectionView: UIView, UICollectionViewDataSource, UICollectionViewDe
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! DataCellView
cell.isDataView = self.isDataView
cell.selectionBand = self.selectionBand
cell.menuTranslations = self.menuTranslations
cell.dataCollectionView = self
cell.backgroundColor = isDataView ? indexPath.row % 2 == 0 ? .white : UIColor(red: 0.97, green: 0.97, blue: 0.97, alpha: 1.0) : .white
cell.cellColor = cellColor
cell.onExpandedCellEvent = onExpandedCell
cell.numberOfLines = cellStyle.rowHeight ?? 1
if let data = dataRows, let columnWidths = columnWidths, let dataColumns = dataColumns {
let dataRow = data[indexPath.row]
cell.selectionsEngine = self.selectionsEngine
cell.setData(row: dataRow, withColumns: dataColumns[dataRange],
dataColumns: dataColumns,
columnWidths: columnWidths.columnWidths,
theme: tableTheme!,
selectionsEngine: selectionsEngine!,
Expand Down

0 comments on commit a071134

Please sign in to comment.