Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Swift 6]: Update window system exercise #827

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 29 additions & 6 deletions exercises/concept/windowing-system/.docs/hints.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,47 @@
## 1. Define a Size struct

- Properties must be defined as `var`s if they can be changed.
- The height and width properties should be given the default values of 80 and 60, respectively.
- Methods in a struct must be marked `mutating` if they change properties of the struct.

## 2. Define a Position struct

- Properties must be defined as `var`s if they can be changed.
- The x and y properties should be given the default values of 0.
- Methods in a struct must be marked `mutating` if they change properties of the struct.

## 3. Define a Window class

- Structs can be initialized with different property values using [memberwise initializers][memberwise-initializers].
- Constant properties should be defined using `let`.
- Properties can be changed using their own methods, where available.
- The `contents` property should be optional, as it may not have a value.
- You have to define an empty initializer for the class (`init() {}`).

## 4. Create some Windows
## 4. Add a method to resize windows

- The method should take a `to` parameter of type `Size`.
- It is possible to extract the width and height from the `to` parameter using dot notation.

## 5. Add a method to move windows

- The method should take a `to` parameter of type `Position`.
- It is possible to extract the x and y from the `to` parameter using dot notation.

## 6. Add a method to set the contents of a window

- It is possible to have two methods with the same name but different parameters in Swift.
- Deffine a method with the parameter `title` that sets the `title` property.
- Deffine a method with the parameter `text` that sets the `contents` property.
- Define a display method that prints the window's title and contents.

## 7. Create an initilazer for the Window class

- The class should have two initializers, one that takes no parameters and one that takes parameters.
- The new initializer should have the parameters `title`, and `contents`, it should also allow the optional parameters `size` and `position`
If no parameters are provided, the default values should be used.
- Optional parameters can be achived by using [default parameters vales][default-parameters-vales].

- This will require the class to be both initialized and modified.
- Initialization and modification is often done [using a closure][initializing-via-closure]

[structs-and-classes]: https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html
[memberwise-initializers]: https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html#ID87
[initializing-via-closure]: https://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID232
[memberwise-initializers]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/classesandstructures/#Memberwise-Initializers-for-Structure-Types
[default-parameters-vales]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions#Default-Parameter-Values
55 changes: 42 additions & 13 deletions exercises/concept/windowing-system/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Instructions

In this exercise, you will be simulating a windowing based computer system. You will create some windows that can be moved and resized and display their contents. The following image is representative of the values you will be working with below.
In this exercise, you will be simulating a windowing based computer system.
You will create some windows that can be moved and resized and display their contents.
The following image is representative of the values you will be working with below.

```
<--------------------- screenSize.width --------------------->
Expand All @@ -26,30 +28,32 @@ screenSize.height ║ | │ │

## 1. Define a Size struct

Define a struct named `Size` with two `Int` properties, `width` and `height` that store the window's current width and height, respectively. The initial width and height should be 80 and 60, respectively. Include a method `resize(newWidth:newHeight:)` that takes new width and height parameters and changes the properties to reflect the new size.
Define a struct named `Size` with two `Int` properties, `width` and `height` that store the window's current width and height, respectively. The initial width and height should be 80 and 60, respectively.
Include a method `resize(newWidth:newHeight:)` that takes new width and height parameters and changes the properties to reflect the new size.

```swift
let size1080x764 = Size(width: 1080, height: 764)
// => Size
// returns Size
var size1200x800 = size1080x764
// => Size
// returns Size
size1200x800.resize(newWidth: 1200, newHeight: 800)
size1200x800.height
// => 800
// returns 800
```

## 2. Define a Position struct

Define a struct named `Position` with two `Int` properties, `x` and `y` that store the current horizontal and vertical position, respectively, of the window's upper left corner. The initial values of x and y should each be 0. The position (0, 0) is the upper left corner of the screen with `x` values getting larger as you move right and `y` values getting larger as you move down.
Define a struct named `Position` with two `Int` properties, `x` and `y` that store the current horizontal and vertical position, respectively, of the window's upper left corner.
The initial values of x and y should each be 0. The position (0, 0) is the upper left corner of the screen with `x` values getting larger as you move right and `y` values getting larger as you move down.

Include a method `moveTo(newX:newY:)` that takes new x and y parameters and changes the properties to reflect the new position.

```swift
var point = Position(x: 10, y: 20)
// => Position
// returns Position
point.moveTo(newX: 100, newY: -100)
point.y
// => -100
// returns -100
```

## 3. Define a Window class
Expand All @@ -62,22 +66,47 @@ Define a window class with the following properties:
- `position` : `Position`, initial value is the default value of the `Position` struct
- `contents` : `String?`, initial value is `nil`

You should also define an empty initializer for the class.

```swift
let window = Window()
window.title
// returns "New Window"
```

## 4. Add a method to resize windows

- `resize(to:)` : `(Size) -> ()` - This method takes a `Size` struct as input and attempts to resize the window to the specified size. However, the new size cannot exceed certain bounds. - The minimum allowed height or width is 1. Requested heights or widths less than 1 will be clipped to 1. - The maximum height and width depends on the current position of the window, the edges of the window cannot move past the edges of the screen. Values larger than these bounds will be clipped to the largest size they can take. E.g. if the window's position is at `x` = 400, `y` = 300 and a resize to `height` = 400, `width` = 300 is requested, then the window would be resized to `height` = 300, `width` = 300 as the screen is not large enough in the `y` direction to fully accommodate the request.
- `resize(to:)` : `(Size) -> ()` - This method takes a `Size` struct as input and attempts to resize the window to the specified size. However, the new size cannot exceed certain bounds.
- The minimum allowed height or width is 1. Requested heights or widths less than 1 will be clipped to 1.
- The maximum height and width depends on the current position of the window, the edges of the window cannot move past the edges of the screen.
Values larger than these bounds will be clipped to the largest size they can take. E.g. if the window's position is at `x` = 400, `y` = 300 and a resize to `height` = 400, `width` = 300 is requested, then the window would be resized to `height` = 300, `width` = 300 as the screen is not large enough in the `y` direction to fully accommodate the request.

## 5. Add a method to move windows

- `move(to:)` : `(Position) -> ()` - This is similar to `resize(to:)`, however, this method adjusts the _position_ of the window to the requested value, rather than the size. As with `resize` the new position cannot exceed certain limits. - The smallest position is 0 for both `x` and `y`. - The maximum position in either direction depends on the current size of the window; the edges cannot move past the edges of the screen. Values larger than these bounds will be clipped to the largest size they can take. E.g. if the window's size is at `x` = 250, `y` = 100 and a move to `x` = 600, `y` = 200 is requested, then the window would be moved to `x` = 550, `y` = 200 as the screen is not large enough in the `x` direction to fully accommodate the request.
- `move(to:)` : `(Position) -> ()` - This is similar to `resize(to:)`, however, this method adjusts the _position_ of the window to the requested value, rather than the size. As with `resize` the new position cannot exceed certain limits.
- The smallest position is 0 for both `x` and `y`.
- The maximum position in either direction depends on the current size of the window; the edges cannot move past the edges of the screen.
Values larger than these bounds will be clipped to the largest size they can take. E.g. if the window's size is at `x` = 250, `y` = 100 and a move to `x` = 600, `y` = 200 is requested, then the window would be moved to `x` = 550, `y` = 200 as the screen is not large enough in the `x` direction to fully accommodate the request.

## 6. Add methods to update the window text and display window information

- `update(title:)` : `(String) -> ()` - This method sets the `title` property to the value of the string that was passed in.
- `update(text:)` : `(String?) -> ()` - This method sets the `contents` property to the value of the optional string that was passed in.
- `display()` : `() -> String` - This method returns a string describing the current state of the window. For example, if the window has the `title` "My First Window" with position: x = 10, y = 100; size: width = 200, height = 150; and contents: "I 😍 my window", it should return the string: `"My First Window\nPosition: (10, 100), Size: (200 x 150)\nI 😍 my window\n"` - If `contents` is nil, the last line should read "[This window intentionally left blank]"

## 7. Create a new Window
## 7. Create an initilazer for the Window class

Create an instances of the Window class and modify it via their methods as follows:
The window system should have an initializer so the that the window can be created with custom inputs.
Create **another** initializer for the `Window` class.
The initializer should take the following parameters: `title`, `contents`, and two optional parameters `size` and `position`.
The `size` and `position` parameters should default to the default values of the `Size` and `Position` structs.

- The window should be given the title "Main Window", with a width of 400, a height of 300 and positioned at x = 100, y = 100. Its contents should be "This is the main window". Assign this instance to the name `mainWindow`.
```swift
let window = Window(title: "My First Window", contents: "I 😍 my window")
window.display()
// returns "My First Window\nPosition: (0, 0), Size: (80 x 60)\nI 😍 my window\n"

let window2 = Window(title: "My Second Window", contents: "I 😍 my window", size: Size(width: 200, height: 150), position: Position(x: 10, y: 100))
window2.display()
// returns "My Second Window\nPosition: (10, 100), Size: (200 x 150)\nI 😍 my window\n"
```
Original file line number Diff line number Diff line change
@@ -1,13 +1,3 @@
struct Position {
var x = 0
var y = 0

mutating func moveTo(newX: Int, newY: Int) {
x = newX
y = newY
}
}

struct Size {
var width = 80
var height = 60
Expand All @@ -18,13 +8,32 @@ struct Size {
}
}

class Window: @unchecked Sendable {
struct Position {
var x = 0
var y = 0

mutating func moveTo(newX: Int, newY: Int) {
x = newX
y = newY
}
}

class Window {
var title = "New Window"
let screenSize = Size(width: 800, height: 600)
var size = Size()
var position = Position()
var contents: String?

init() {}

init(title: String, contents: String?, size : Size = Size(), position: Position = Position()) {
self.title = title
self.contents = contents
self.size = size
self.position = position
}

func move(to newPosition: Position) {
let minX = min(max(0, newPosition.x), screenSize.width - size.width)
let minY = min(max(0, newPosition.y), screenSize.height - size.height)
Expand All @@ -45,12 +54,3 @@ class Window: @unchecked Sendable {
"\(title)\nPosition: (\(position.x), \(position.y)), Size: (\(size.width) x \(size.height))\n\(contents ?? "[This window intentionally left blank]")\n"
}
}

let mainWindow: Window = {
var window = Window()
window.title = "Main Window"
window.contents = "This is the main window"
window.move(to: Position(x: 100, y: 100))
window.resize(to: Size(width: 400, height: 300))
return window
}()
3 changes: 3 additions & 0 deletions exercises/concept/windowing-system/.meta/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
"authors": [
"wneumann"
],
"contributors": [
"meatball133"
],
"files": {
"solution": [
"Sources/WindowingSystem/WindowingSystem.swift"
Expand Down
44 changes: 22 additions & 22 deletions exercises/concept/windowing-system/Package.swift
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
// swift-tools-version:5.3
// swift-tools-version:6.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "WindowingSystem",
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "WindowingSystem",
targets: ["WindowingSystem"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "WindowingSystem",
dependencies: []),
.testTarget(
name: "WindowingSystemTests",
dependencies: ["WindowingSystem"]),
]
name: "WindowingSystem",
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "WindowingSystem",
targets: ["WindowingSystem"])
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "WindowingSystem",
dependencies: []),
.testTarget(
name: "WindowingSystemTests",
dependencies: ["WindowingSystem"]),
]
)
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// TODO: Define the Position struct

// TODO: Define the Size struct

// TODO: Define the Position struct

// TODO: Define the Window class
Loading