0

How can I reformat the code of GridStack in the view body so I may duplicate it per row, such as 1 row of 2 columns, 2 rows of 8 columns, 4 rows of 18 columns, 2 rows of 15 columns?, I am cutting out the holes with this Hypothesis to shape an Interactive Periodic Table, refer to image attached.

@jnpdx has provided an example for display function per cell coordinate, along with this i will need an ontapgesture to operate the overlay of data per cell so I may send information to other menu fields.

@jnpdx so now right before the roundedrectangle in this edit and turn on the display function commented out, i need to some how over lay the custom data per cell instead of hydrogen on every cell plus create an ontapgesture to send globally to other menu fields in the application?

func readiness

struct GridStack<Content: View>: View {
   
    let rows: Int
    let columns: Int
    let content: (Int, Int) -> Content
    
    

    //func shouldDisplayAtCoord(row: Int, column: Int) { if row == 0 && column > 1 { return true } }
    
    var body: some View {
        VStack {
                    ForEach(0 ..< rows, id: \.self) { row in
                       
                        HStack {
                            ForEach(0 ..< columns, id: \.self) { column in
                                ZStack{
                                RoundedRectangle(cornerRadius: 5)
                                            .fill(Color.brown)
                                            .frame(width: 40, height: 50)
                            Image("RadicalDeepscale30").opacity(0.4)
                            content(row, column)
                              
                                 
                            }
                            }
                        }
                    }
                }
       
    }
    init(rows: Int, columns: Int, @ViewBuilder content: @escaping (Int, Int) -> Content) {
        self.rows = rows
        self.columns = columns
        self.content = content
    }
}

// An example view putting GridStack into practice.
struct DETEView: View {
    var body: some View {
        
        VStack(alignment: .center) {
            Text("DART Edge Table of Elements")
                .font(.largeTitle)
                .bold()
                //.colorInvert()
                .padding(.top, 20)
                .shadow(radius: 3)
        }
        
            VStack(alignment: .center) {
                HStack(alignment: .center){
                    VStack(alignment: .center) {
        GridStack(rows: 9, columns: 18) { row, col in
            VStack(alignment: .leading){
                HStack(alignment: .top) {
            VStack(alignment: .leading) {
            Text("1")
                .font(.system(size: 9))
               // .bold()
                //.shadow(radius: 1)
            }
                }
                HStack(alignment: .center) {
                VStack(alignment: .center){
                    Text("H")
                        .font(.system(size: 12))
                        .bold()
                        //.shadow(radius: 1)
            Text("Hydrogen")
                .font(.system(size: 7))
                //.bold()
               // .shadow(radius: 1)
                //.padding(.top, 1)
                }
                }
            }
        }
                    }
                }

            }.frame(width: 950, height: 670, alignment: .top).padding(.top, 20)
    }
        }

      
  • 1
    I'd probably just use the coordinates (eg the row and column numbers) to determine whether to put an element there or an empty view. – jnpdx Nov 06 '21 at 20:08
  • so using row and column is throwing my error? then layout gridstack with the numbers themselves per 118 of the table out of my initial 162? and say for example first row subtract/omit columns 2-17? @jnpdx –  Nov 06 '21 at 21:42
  • I don't really know what any of that is referring to -- what is "my error"? – jnpdx Nov 06 '21 at 21:45
  • @jnpdx see attached image edit –  Nov 06 '21 at 21:46
  • apparently im not able to use gridstack more than once..? @jnpdx –  Nov 06 '21 at 21:46
  • You have compilation errors not shown in the code you've included here. For example, it can't find `Content2View`. There is no problem using `GridStack` more than once. – jnpdx Nov 06 '21 at 21:48
  • However, what I'm suggesting is you use *one* `GridStack` and just hide the views that you don't want shown. – jnpdx Nov 06 '21 at 21:48
  • so would that look like: GridStack(rows: 1,2,3,4,5,6,7,8,9, columns: 0,17,18,19) { row, col in etc....? –  Nov 06 '21 at 21:50
  • No. Use a GridStack with 9 rows and 19 columns. When you go to render an item (where you have the `RoundedRectangle`), test `row` and `column` to see if you should actually render a view there. If not, render a clear `RoundedRectangle` or something else that takes the correct amount of space. – jnpdx Nov 06 '21 at 21:53
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/238950/discussion-between-justin-venable-and-jnpdx). –  Nov 06 '21 at 22:01
  • @jnpdx check out the updated post :), I actually, after our last chat updated the layout with a bunch of stacks containers to display a completed periodic table layout then i read your last post and i decided i had better use the shoulddisplayfunction to go with the updated post question, see above. –  Nov 08 '21 at 16:48
  • @jnpdx so now right before the roundedrectangle in this edit and turn on the display function commented out, i need to some how over lay the custom data per cell instead of hydrogen on every cell plus create an ontapgesture to send globally to other menu fields in the application? –  Nov 08 '21 at 16:56
  • Sounds like a lot. Is there a singular question or issue you can pare this down to? For example, is it just the layout issue to be answered here? – jnpdx Nov 08 '21 at 17:03
  • @jnpdx just layout, i should able to add the data needed and use the same layout function once i learn how to format the func code on a grid, i see how the foreach works and can research other articles, but to use a function that you described in the foreach is a little tricky with and error right now. –  Nov 08 '21 at 17:09

1 Answers1

0

This is a simple implementation using a similar strategy to what we discussed in the comments/chat. In this case, instead of using a function to determine whether the element should be displayed, it just looks it up in a table that lists the elements and stores them based on their coordinates on the grid.

struct GridStack<Content: View>: View {
    
    let rows: Int
    let columns: Int
    let content: (Int, Int) -> Content
    
    var body: some View {
        VStack {
            ForEach(0 ..< rows, id: \.self) { row in
                HStack {
                    ForEach(0 ..< columns, id: \.self) { column in
                        content(row,column)
                    }
                }
            }
        }
    }
}

struct ElementCoordinate: Hashable {
    var row : Int
    var column: Int
}

struct Element {
    var atomicNumber: Int
    var name : String
}

let tableOfElements : [ElementCoordinate:Element] = [
    ElementCoordinate(row: 1, column: 1):Element(atomicNumber: 1, name: "Hydrogen"),
    ElementCoordinate(row: 1, column: 18):Element(atomicNumber: 2, name: "Helium"),
    ElementCoordinate(row: 2, column: 1):Element(atomicNumber: 3, name: "Lithium"),
    ElementCoordinate(row: 2, column: 2):Element(atomicNumber: 4, name: "Beryllium"),
    ElementCoordinate(row: 2, column: 13):Element(atomicNumber: 5, name: "Boron"),
    ElementCoordinate(row: 2, column: 14):Element(atomicNumber: 6, name: "Carbon"),
]

struct ContentView: View {
    var body: some View {
        GridStack(rows: 9, columns: 18) { row, column in
            ZStack{
                if let element = tableOfElements[ElementCoordinate(row: row + 1, column: column + 1)] {
                    RoundedRectangle(cornerRadius: 5)
                        .fill(Color.brown)
                    Image("RadicalDeepscale30").opacity(0.4)
                    Text(element.name)
                }
            }
            .frame(width: 40, height: 50)
        }
    }
}

Note the + 1 on the row and column numbers when querying the grid, since row and column are zero-based in the Swift code, but my tableOfElements starts with an index of 1.

This should show you not only how to do the layout, but how to associate each coordinate with a specific element.

Obviously the implementation details may change to fit your own model, but this should give you an idea of how to get started.

enter image description here

jnpdx
  • 45,847
  • 6
  • 64
  • 94
  • check it out: https://static.wixstatic.com/media/fe9774_487a11f4dbc24fcd862cefd83eae5354~mv2.png –  Nov 08 '21 at 20:55
  • https://static.wixstatic.com/media/fe9774_56858e7f6d984e169e4f629d1817bec7~mv2.png –  Nov 08 '21 at 21:25
  • thank you so much @jnpdx https://static.wixstatic.com/media/fe9774_10453a70f192460f9e3eb07e89dd6f52~mv2.png –  Nov 08 '21 at 22:44
  • Great -- please consider upvoting as well as accepting if it was useful – jnpdx Nov 08 '21 at 22:51
  • I think im going to create structs and coordinates for each type of element, alkaline, rare earth, noble gas etc... so i may color code the backdrop and aswell enhance interactive data experience @jnpdx right now i switched to a custom image instead of rounded-rectangle, i dont really need color codes but someone might like it and will pave way for partner plugin simulations. realtime graphics are always the best :) –  Nov 09 '21 at 00:21