or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

borders.mdcomponents.mdcore-builder.mddata-binding.mdindex.mdlayouts.mdmenus.mdtables.md

tables.mddocs/

0

# Table Support

1

2

Groovy Swing provides comprehensive table support with enhanced models, custom columns, renderers, and sorters for building data-driven table interfaces.

3

4

## Basic Table Components

5

6

Core table components for displaying tabular data.

7

8

```groovy { .api }

9

// Table component

10

def table(Map attributes = [:], Closure closure = null)

11

12

// Table structure

13

def tableModel(Map attributes = [:], Closure closure = null)

14

def columnModel(Map attributes = [:])

15

def tableColumn(Map attributes = [:])

16

17

// Column types

18

def column(Map attributes = [:])

19

def propertyColumn(Map attributes = [:])

20

def closureColumn(Map attributes = [:])

21

```

22

23

## Table Models

24

25

Enhanced table models with ValueModel integration and data binding support.

26

27

```groovy { .api }

28

// Default table model with enhanced features

29

class DefaultTableModel extends AbstractTableModel {

30

DefaultTableModel()

31

DefaultTableModel(List rowData, List columnNames)

32

33

// ValueModel integration

34

ValueModel getValueModel(int row, int column)

35

void setValueModel(ValueModel model, int row, int column)

36

}

37

38

// Table model factory attributes:

39

// list: List - row data as list of maps or objects

40

// columns: List - column definitions

41

// sortable: boolean - enable sorting support

42

```

43

44

### Basic Table Examples

45

46

```groovy

47

def swing = new SwingBuilder()

48

49

// Simple table with data

50

def tableData = [

51

[name: 'John', age: 30, city: 'New York'],

52

[name: 'Jane', age: 25, city: 'Los Angeles'],

53

[name: 'Bob', age: 35, city: 'Chicago']

54

]

55

56

swing.frame(title: 'Simple Table') {

57

scrollPane {

58

table(

59

model: tableModel(list: tableData) {

60

propertyColumn(header: 'Name', propertyName: 'name', width: 100)

61

propertyColumn(header: 'Age', propertyName: 'age', width: 50)

62

propertyColumn(header: 'City', propertyName: 'city', width: 120)

63

}

64

)

65

}

66

}

67

68

// Table with explicit column model

69

swing.scrollPane {

70

table {

71

// Define table model

72

tableModel(list: tableData)

73

74

// Define column model

75

columnModel {

76

column(header: 'Name', width: 100)

77

column(header: 'Age', width: 50)

78

column(header: 'City', width: 120)

79

}

80

}

81

}

82

```

83

84

## Column Types

85

86

Different column types for various data display and editing scenarios.

87

88

### Property Columns

89

90

```groovy { .api }

91

def propertyColumn(Map attributes = [:])

92

93

// PropertyColumn attributes:

94

// header: String - column header text

95

// propertyName: String - property name to bind to

96

// type: Class - property type for editing

97

// width: int - preferred column width

98

// editable: boolean - whether column is editable

99

// renderer: TableCellRenderer - custom renderer

100

// editor: TableCellEditor - custom editor

101

```

102

103

### Closure Columns

104

105

```groovy { .api }

106

def closureColumn(Map attributes = [:])

107

108

// ClosureColumn attributes:

109

// header: String - column header text

110

// read: Closure - closure to read value from row object

111

// write: Closure - closure to write value to row object (optional)

112

// type: Class - value type

113

// width: int - preferred column width

114

// editable: boolean - whether column is editable

115

```

116

117

### Column Examples

118

119

```groovy

120

def people = [

121

new Person(firstName: 'John', lastName: 'Doe', age: 30),

122

new Person(firstName: 'Jane', lastName: 'Smith', age: 25)

123

]

124

125

swing.scrollPane {

126

table(model: tableModel(list: people)) {

127

// Property-based columns

128

propertyColumn(

129

header: 'First Name',

130

propertyName: 'firstName',

131

width: 100,

132

editable: true

133

)

134

135

propertyColumn(

136

header: 'Last Name',

137

propertyName: 'lastName',

138

width: 100,

139

editable: true

140

)

141

142

propertyColumn(

143

header: 'Age',

144

propertyName: 'age',

145

type: Integer,

146

width: 50,

147

editable: true

148

)

149

150

// Closure-based computed column

151

closureColumn(

152

header: 'Full Name',

153

read: { row -> "${row.firstName} ${row.lastName}" },

154

width: 150,

155

editable: false

156

)

157

158

// Closure column with custom formatting

159

closureColumn(

160

header: 'Status',

161

read: { row -> row.age >= 30 ? 'Senior' : 'Junior' },

162

width: 80

163

)

164

}

165

}

166

```

167

168

## Table Cell Renderers

169

170

Custom renderers for specialized cell display.

171

172

```groovy { .api }

173

// Renderer factories

174

def tableCellRenderer(Map attributes = [:])

175

def listCellRenderer(Map attributes = [:])

176

def cellRenderer(Map attributes = [:])

177

def headerRenderer(Map attributes = [:])

178

179

// Renderer update factory

180

def onRender(Closure renderClosure)

181

```

182

183

### Renderer Examples

184

185

```groovy

186

swing.scrollPane {

187

table(model: tableModel(list: salesData)) {

188

propertyColumn(header: 'Product', propertyName: 'product')

189

190

propertyColumn(header: 'Revenue', propertyName: 'revenue') {

191

// Custom currency renderer

192

tableCellRenderer { renderer, table, value, isSelected, hasFocus, row, column ->

193

renderer.text = NumberFormat.getCurrencyInstance().format(value)

194

if (value > 10000) {

195

renderer.foreground = Color.GREEN

196

renderer.font = renderer.font.deriveFont(Font.BOLD)

197

} else {

198

renderer.foreground = Color.BLACK

199

renderer.font = renderer.font.deriveFont(Font.PLAIN)

200

}

201

return renderer

202

}

203

}

204

205

propertyColumn(header: 'Status', propertyName: 'status') {

206

// Icon renderer based on status

207

tableCellRenderer { renderer, table, value, isSelected, hasFocus, row, column ->

208

renderer.text = value

209

renderer.icon = value == 'Active' ? activeIcon : inactiveIcon

210

return renderer

211

}

212

}

213

214

// Progress bar renderer for percentage column

215

propertyColumn(header: 'Progress', propertyName: 'percentage') {

216

tableCellRenderer { renderer, table, value, isSelected, hasFocus, row, column ->

217

def progressBar = new JProgressBar(0, 100)

218

progressBar.value = value

219

progressBar.stringPainted = true

220

progressBar.string = "${value}%"

221

return progressBar

222

}

223

}

224

}

225

}

226

```

227

228

## Table Cell Editors

229

230

Custom editors for specialized cell editing.

231

232

```groovy { .api }

233

// Editor factories

234

def cellEditor(Map attributes = [:])

235

def editorValue(Closure valueClosure)

236

def prepareEditor(Closure prepareClosure)

237

```

238

239

### Editor Examples

240

241

```groovy

242

swing.scrollPane {

243

table(model: tableModel(list: employeeData)) {

244

propertyColumn(header: 'Name', propertyName: 'name')

245

246

propertyColumn(header: 'Department', propertyName: 'department') {

247

// Combo box editor

248

cellEditor {

249

comboBox(items: ['Sales', 'Marketing', 'Engineering', 'HR'])

250

}

251

}

252

253

propertyColumn(header: 'Salary', propertyName: 'salary') {

254

// Formatted text field editor

255

cellEditor {

256

formattedTextField(format: NumberFormat.getCurrencyInstance())

257

}

258

}

259

260

propertyColumn(header: 'Start Date', propertyName: 'startDate') {

261

// Custom date picker editor

262

cellEditor {

263

bean(class: 'com.toedter.calendar.JDateChooser')

264

}

265

266

// Custom value extraction

267

editorValue { editor ->

268

return editor.date

269

}

270

271

// Custom editor preparation

272

prepareEditor { editor, table, value, isSelected, row, column ->

273

editor.date = value

274

return editor

275

}

276

}

277

}

278

}

279

```

280

281

## Table Sorting

282

283

Built-in sorting support with TableSorter integration.

284

285

```groovy { .api }

286

// TableSorter class for sortable table models

287

class TableSorter extends TableMap {

288

TableSorter(TableModel model)

289

290

void setTableHeader(JTableHeader tableHeader)

291

boolean isSorting()

292

int getSortingStatus(int column)

293

void setSortingStatus(int column, int status)

294

}

295

296

// Sorting constants

297

// DESCENDING = -1

298

// NOT_SORTED = 0

299

// ASCENDING = 1

300

```

301

302

### Sorting Examples

303

304

```groovy

305

import groovy.swing.table.TableSorter

306

307

def tableData = [

308

[name: 'Alice', age: 30, salary: 50000],

309

[name: 'Bob', age: 25, salary: 45000],

310

[name: 'Charlie', age: 35, salary: 60000]

311

]

312

313

swing.frame(title: 'Sortable Table') {

314

scrollPane {

315

def tableModel = tableModel(list: tableData)

316

def sorter = new TableSorter(tableModel)

317

318

table(model: sorter) {

319

// Connect sorter to table header for click sorting

320

sorter.setTableHeader(it.tableHeader)

321

322

propertyColumn(header: 'Name', propertyName: 'name')

323

propertyColumn(header: 'Age', propertyName: 'age', type: Integer)

324

propertyColumn(header: 'Salary', propertyName: 'salary', type: Integer)

325

}

326

}

327

}

328

329

// Programmatic sorting

330

sorter.setSortingStatus(1, TableSorter.ASCENDING) // Sort by age ascending

331

```

332

333

## Table Selection and Events

334

335

Table selection handling and event processing.

336

337

```groovy { .api }

338

// Selection binding support

339

// selectedRow: int - selected row index

340

// selectedColumn: int - selected column index

341

// selectedElement: Object - selected row object

342

// selectedElements: List - multiple selected objects

343

```

344

345

### Selection Examples

346

347

```groovy

348

def selectedPerson = new ValueHolder()

349

350

swing.frame(title: 'Table Selection') {

351

borderLayout()

352

353

// Table with selection binding

354

scrollPane(constraints: BorderLayout.CENTER) {

355

table(

356

model: tableModel(list: people),

357

selectedElement: bind(source: selectedPerson, sourceProperty: 'value')

358

) {

359

propertyColumn(header: 'Name', propertyName: 'name')

360

propertyColumn(header: 'Age', propertyName: 'age')

361

}

362

}

363

364

// Detail panel showing selected person

365

panel(constraints: BorderLayout.SOUTH) {

366

label(text: bind(

367

source: selectedPerson,

368

sourceProperty: 'value',

369

converter: { person ->

370

person ? "Selected: ${person.name} (${person.age})" : "No selection"

371

}

372

))

373

}

374

}

375

376

// Multiple selection

377

swing.table(

378

selectionMode: ListSelectionModel.MULTIPLE_INTERVAL_SELECTION,

379

selectedElements: bind(source: selectedItems, sourceProperty: 'value')

380

) {

381

// Table columns...

382

}

383

```

384

385

## Advanced Table Features

386

387

### Custom Table Models

388

389

```groovy

390

// Custom table model with live data

391

class LiveDataTableModel extends DefaultTableModel {

392

void startUpdating() {

393

timer = new Timer(1000) {

394

// Update data periodically

395

fireTableDataChanged()

396

}

397

timer.start()

398

}

399

}

400

401

swing.table(model: new LiveDataTableModel()) {

402

// Column definitions...

403

}

404

```

405

406

### Table with Filtering

407

408

```groovy

409

def originalData = [/* data */]

410

def filteredData = new FilteredListModel(originalData)

411

def filterText = new ValueHolder('')

412

413

swing.frame(title: 'Filtered Table') {

414

borderLayout()

415

416

// Filter input

417

panel(constraints: BorderLayout.NORTH) {

418

label(text: 'Filter:')

419

textField(

420

columns: 20,

421

text: bind(source: filterText, sourceProperty: 'value')

422

) {

423

// Apply filter on text change

424

bind(source: filterText, sourceProperty: 'value') { newValue ->

425

filteredData.filter = { item ->

426

item.name.toLowerCase().contains(newValue.toLowerCase())

427

}

428

}

429

}

430

}

431

432

// Filtered table

433

scrollPane(constraints: BorderLayout.CENTER) {

434

table(model: tableModel(list: filteredData)) {

435

propertyColumn(header: 'Name', propertyName: 'name')

436

propertyColumn(header: 'Description', propertyName: 'description')

437

}

438

}

439

}

440

```