1+ package processing.app.ui
2+
3+ import androidx.compose.foundation.Image
4+ import androidx.compose.foundation.clickable
5+ import androidx.compose.foundation.layout.*
6+ import androidx.compose.foundation.lazy.LazyColumn
7+ import androidx.compose.foundation.lazy.grid.*
8+ import androidx.compose.material.icons.outlined.Info
9+ import androidx.compose.ui.graphics.Color
10+ import androidx.compose.foundation.background
11+ import androidx.compose.foundation.lazy.items
12+ import androidx.compose.material.Text
13+ import androidx.compose.material.icons.Icons
14+ import androidx.compose.material.*
15+ import androidx.compose.material.icons.outlined.Add
16+ import androidx.compose.material.icons.outlined.AddCircle
17+ import androidx.compose.material.icons.outlined.Build
18+ import androidx.compose.material.icons.outlined.Face
19+ import androidx.compose.material.icons.outlined.MailOutline
20+ import androidx.compose.runtime.*
21+ import androidx.compose.ui.Alignment
22+ import androidx.compose.ui.Modifier
23+ import androidx.compose.ui.graphics.vector.ImageVector
24+ import androidx.compose.ui.unit.dp
25+ import androidx.compose.ui.window.*
26+
27+ data class SketchItem (
28+ val name : String ,
29+ val isFolder : Boolean ,
30+ val lastModified : Long = 0L // default for folders
31+ )
32+
33+ fun main () = application {
34+ Window (
35+ onCloseRequest = ::exitApplication,
36+ title = " Sketchbook Prototype" ,
37+ state = WindowState (width = 800 .dp, height = 600 .dp, position = WindowPosition (Alignment .Center ))
38+ ) {
39+ Sketchbook ()
40+ }
41+ }
42+
43+ @Composable
44+ fun Sketchbook () {
45+ // TODO: Replace dummy data with reading from folder.
46+ val sketchList = listOf (
47+ SketchItem (" Fun" , false , 1680000000000 ),
48+ SketchItem (" Cute" , false , 1660000000000 ),
49+ SketchItem (" MyFolder" , true ),
50+ SketchItem (" Silly" , false , 1670000000000 ),
51+ )
52+
53+ var sortOption by remember { mutableStateOf(" Recently Updated" ) }
54+
55+ val sortedSketches = when (sortOption) {
56+ " Alphabetical" -> sketchList.sortedBy { it.name.lowercase() }
57+ " Recently Updated" -> sketchList.sortedByDescending { it.lastModified }
58+ else -> sketchList
59+ }
60+
61+
62+ Row (Modifier .fillMaxSize()) {
63+ Column (
64+ modifier = Modifier
65+ .weight(0.35f )
66+ .fillMaxHeight()
67+ .padding(8 .dp)
68+ ) {
69+ Sidebar (sketchList)
70+ }
71+
72+ Column (
73+ modifier = Modifier
74+ .weight(0.65f )
75+ .fillMaxHeight()
76+ .padding(8 .dp)
77+ ) {
78+ MainSketchGrid (
79+ sketches = sortedSketches.filter { ! it.isFolder },
80+ selectedFolder = null ,
81+ searchQuery = " " ,
82+ sortOption = sortOption,
83+ onSortChange = { sortOption = it }
84+ )
85+ }
86+ }
87+ }
88+
89+ @Composable
90+ fun Sidebar (sketches : List <SketchItem >) {
91+ var searchText by remember { mutableStateOf(" " ) }
92+
93+ Column (
94+ modifier = Modifier .fillMaxHeight().width(350 .dp)
95+ ) {
96+ Row (
97+ modifier = Modifier
98+ .fillMaxWidth()
99+ .padding(8 .dp),
100+ verticalAlignment = Alignment .CenterVertically
101+ ) {
102+ Column () {
103+ Text (
104+ text = " Sketchbook" ,
105+ style = MaterialTheme .typography.h4,
106+ )
107+ TextField (
108+ value = searchText,
109+ onValueChange = { searchText = it },
110+ placeholder = { Text (" Search..." ) },
111+ modifier = Modifier .fillMaxWidth()
112+ )
113+ }
114+ }
115+
116+ LazyColumn (
117+ modifier = Modifier
118+ .fillMaxSize()
119+ .weight(1f )
120+ .padding(8 .dp)
121+ ) {
122+
123+ items(sketches) { sketch ->
124+ SketchRow (sketch)
125+ }
126+ }
127+
128+ Row (
129+ modifier = Modifier
130+ .fillMaxWidth()
131+ .padding(8 .dp),
132+ horizontalArrangement = Arrangement .spacedBy(8 .dp),
133+ verticalAlignment = Alignment .CenterVertically
134+ ) {
135+ Button (onClick = { println (" Clicked track folder" ) },
136+ modifier = Modifier
137+ .weight(1f )
138+ .height(48 .dp),
139+ contentPadding = PaddingValues (
140+ start = 8 .dp, // less left padding (default is 16.dp)
141+ top = 12 .dp,
142+ end = 16 .dp,
143+ bottom = 12 .dp
144+ )
145+ ) {
146+ Image (
147+ imageVector = Icons .Outlined .Build ,
148+ contentDescription = null ,
149+ modifier = Modifier .size(16 .dp)
150+ )
151+ Spacer (modifier = Modifier .width(8 .dp))
152+ Text (" Track Folder" )
153+ }
154+ Button (onClick = { println (" Clicked add folder" ) },
155+ modifier = Modifier
156+ .weight(1f )
157+ .height(48 .dp),
158+ contentPadding = PaddingValues (
159+ start = 8 .dp, // less left padding (default is 16.dp)
160+ top = 12 .dp,
161+ end = 16 .dp,
162+ bottom = 12 .dp
163+ )
164+ ) {
165+ Image (
166+ imageVector = Icons .Outlined .AddCircle ,
167+ contentDescription = null ,
168+ modifier = Modifier .size(16 .dp)
169+ )
170+ Spacer (modifier = Modifier .width(8 .dp))
171+ Text (" New Folder" )
172+ }
173+ }
174+ }
175+ }
176+
177+ @Composable
178+ fun SketchRow (sketch : SketchItem ) {
179+ Row (
180+ modifier = Modifier
181+ .fillMaxWidth()
182+ .padding(4 .dp)
183+ .clickable { println (" Clicked on ${sketch.name} " ) },
184+ verticalAlignment = Alignment .CenterVertically
185+ ) {
186+ val icon: ImageVector = if (sketch.isFolder) Icons .Outlined .MailOutline else Icons .Outlined .Face
187+ Image (
188+ imageVector = icon,
189+ contentDescription = null ,
190+ modifier = Modifier .size(24 .dp)
191+ )
192+ Spacer (modifier = Modifier .width(8 .dp))
193+ Text (text = sketch.name)
194+ }
195+ }
196+
197+ @Composable
198+ fun MainSketchGrid (
199+ sketches : List <SketchItem >,
200+ selectedFolder : String? ,
201+ searchQuery : String ,
202+ sortOption : String ,
203+ onSortChange : (String ) -> Unit
204+ ) {
205+ val displayedHeader = when {
206+ selectedFolder != null -> selectedFolder
207+ searchQuery.isNotBlank() -> " Search results for \" $searchQuery \" "
208+ else -> " All Sketches"
209+ }
210+
211+ var expanded by remember { mutableStateOf(false ) }
212+
213+ Column (modifier = Modifier .fillMaxSize().padding(16 .dp)) {
214+ Text (
215+ text = displayedHeader,
216+ style = MaterialTheme .typography.h5,
217+ modifier = Modifier .padding(bottom = 8 .dp)
218+ )
219+
220+ Box {
221+ Button (onClick = { expanded = true }) {
222+ Text (" Sort by: $sortOption " )
223+ }
224+
225+ DropdownMenu (
226+ expanded = expanded,
227+ onDismissRequest = { expanded = false }
228+ ) {
229+ DropdownMenuItem (onClick = {
230+ onSortChange(" Recently Updated" )
231+ expanded = false
232+ }) {
233+ Text (" Recently Updated" )
234+ }
235+ DropdownMenuItem (onClick = {
236+ onSortChange(" Alphabetical" )
237+ expanded = false
238+ }) {
239+ Text (" Alphabetical" )
240+ }
241+ }
242+ }
243+
244+ Spacer (Modifier .height(16 .dp))
245+
246+ LazyVerticalGrid (
247+ columns = GridCells .Adaptive (minSize = 160 .dp),
248+ modifier = Modifier .fillMaxSize(),
249+ verticalArrangement = Arrangement .spacedBy(16 .dp),
250+ horizontalArrangement = Arrangement .spacedBy(16 .dp)
251+ ) {
252+ item {
253+ AddNewSketchCard ()
254+ }
255+ items(sketches) { sketch ->
256+ SketchCard (sketch)
257+ }
258+ }
259+ }
260+ }
261+
262+ @Composable
263+ fun AddNewSketchCard () {
264+ Card (
265+ modifier = Modifier .fillMaxWidth(),// .aspectRatio(1f), // square
266+ elevation = 4 .dp
267+ ) {
268+ Column (
269+ modifier = Modifier .padding(8 .dp)
270+ ) {
271+ Box (
272+ modifier = Modifier
273+ .fillMaxWidth()
274+ .height(100 .dp).clickable {
275+ println (" Clicked to Add New Sketch" )
276+ },
277+ contentAlignment = Alignment .Center
278+ ) {
279+ Text (" +" , color = Color .DarkGray )
280+ Icon (
281+ imageVector = Icons .Outlined .Add ,
282+ contentDescription = " Add New" ,
283+ modifier = Modifier .size(32 .dp)
284+ )
285+ }
286+
287+ Spacer (Modifier .height(8 .dp))
288+
289+ Row (
290+ verticalAlignment = Alignment .CenterVertically ,
291+ horizontalArrangement = Arrangement .SpaceBetween ,
292+ modifier = Modifier .fillMaxWidth()
293+ ) {
294+ Text (" Add New" , style = MaterialTheme .typography.body1)
295+ }
296+ }
297+ }
298+ }
299+
300+ @Composable
301+ fun SketchCard (sketch : SketchItem ) {
302+ Card (
303+ modifier = Modifier .fillMaxWidth().height(160 .dp),// .aspectRatio(1f), // square
304+ elevation = 4 .dp
305+ ) {
306+ Column (
307+ modifier = Modifier .padding(8 .dp)
308+ ) {
309+ Box (
310+ modifier = Modifier
311+ .fillMaxWidth()
312+ .height(100 .dp)
313+ .background(Color .LightGray ).clickable {
314+ println (" Clicked open ${sketch.name} " )
315+ },
316+ contentAlignment = Alignment .Center
317+ ) {
318+ Text (" Thumbnail" , color = Color .DarkGray )
319+ }
320+
321+ Spacer (Modifier .height(8 .dp))
322+
323+ Row (
324+ verticalAlignment = Alignment .CenterVertically ,
325+ horizontalArrangement = Arrangement .SpaceBetween ,
326+ modifier = Modifier .fillMaxWidth()
327+ ) {
328+ Text (sketch.name, style = MaterialTheme .typography.body1)
329+ Icon (
330+ imageVector = Icons .Outlined .Info ,
331+ contentDescription = " Sketch Info" ,
332+ modifier = Modifier .size(20 .dp).clickable {
333+ println (" Clicked info for ${sketch.name} " )
334+ }
335+ )
336+ }
337+ }
338+ }
339+ }
0 commit comments