Initial commit

This commit is contained in:
Kenneth Bruen 2022-05-16 07:03:35 +03:00
commit c8b5168413
Signed by: kbruen
GPG key ID: C1980A470C3EE5B1
118 changed files with 5789 additions and 0 deletions

11
.args Normal file
View file

@ -0,0 +1,11 @@
>Compile Time Argument
-flutter
-build
-linux
>Run Time Argument
-flutter
-run
>Compile Time Working Directory
-logic_circuits_simulator
>Run Time Working Directory
-logic_circuits_simulator

47
.gitignore vendored Normal file
View file

@ -0,0 +1,47 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Web related
lib/generated_plugin_registrant.dart
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release

42
.metadata Normal file
View file

@ -0,0 +1,42 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled.
version:
revision: 13a2fb10b838971ce211230f8ffdd094c14af02c
channel: beta
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 13a2fb10b838971ce211230f8ffdd094c14af02c
base_revision: 13a2fb10b838971ce211230f8ffdd094c14af02c
- platform: android
create_revision: 13a2fb10b838971ce211230f8ffdd094c14af02c
base_revision: 13a2fb10b838971ce211230f8ffdd094c14af02c
- platform: ios
create_revision: 13a2fb10b838971ce211230f8ffdd094c14af02c
base_revision: 13a2fb10b838971ce211230f8ffdd094c14af02c
- platform: linux
create_revision: 13a2fb10b838971ce211230f8ffdd094c14af02c
base_revision: 13a2fb10b838971ce211230f8ffdd094c14af02c
- platform: web
create_revision: 13a2fb10b838971ce211230f8ffdd094c14af02c
base_revision: 13a2fb10b838971ce211230f8ffdd094c14af02c
- platform: windows
create_revision: 13a2fb10b838971ce211230f8ffdd094c14af02c
base_revision: 13a2fb10b838971ce211230f8ffdd094c14af02c
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'

8
.projectInfo Normal file
View file

@ -0,0 +1,8 @@
>JDK Path
null
>Main Class
-
>Language Tag
--1
>Opened Editors on Main Tab Panel
-project-root$/lib/main.dart

6
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,6 @@
{
"files.exclude": {
"**/*.freezed.dart": true,
"**/*.g.dart": true
}
}

16
README.md Normal file
View file

@ -0,0 +1,16 @@
# logic_circuits_simulator
License project
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.

33
analysis_options.yaml Normal file
View file

@ -0,0 +1,33 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at
# https://dart-lang.github.io/linter/lints/index.html.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
analyzer:
errors:
invalid_annotation_target: ignore

13
android/.gitignore vendored Normal file
View file

@ -0,0 +1,13 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks

71
android/app/build.gradle Normal file
View file

@ -0,0 +1,71 @@
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "ro.dcdev.logic_circuits_simulator"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}

View file

@ -0,0 +1,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ro.dcdev.logic_circuits_simulator">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View file

@ -0,0 +1,34 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ro.dcdev.logic_circuits_simulator">
<application
android:label="logic_circuits_simulator"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>

View file

@ -0,0 +1,6 @@
package ro.dcdev.logic_circuits_simulator
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
}

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View file

@ -0,0 +1,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ro.dcdev.logic_circuits_simulator">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

31
android/build.gradle Normal file
View file

@ -0,0 +1,31 @@
buildscript {
ext.kotlin_version = '1.6.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}

View file

@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true

View file

@ -0,0 +1,6 @@
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip

11
android/settings.gradle Normal file
View file

@ -0,0 +1,11 @@
include ':app'
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"

34
ios/.gitignore vendored Normal file
View file

@ -0,0 +1,34 @@
**/dgph
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/ephemeral/
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>9.0</string>
</dict>
</plist>

View file

@ -0,0 +1 @@
#include "Generated.xcconfig"

View file

@ -0,0 +1 @@
#include "Generated.xcconfig"

View file

@ -0,0 +1,481 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
);
path = Runner;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1300;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 1100;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = ro.dcdev.logicCircuitsSimulator;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = ro.dcdev.logicCircuitsSimulator;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = ro.dcdev.logicCircuitsSimulator;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View file

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View file

@ -0,0 +1,13 @@
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}

View file

@ -0,0 +1,122 @@
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View file

@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

View file

@ -0,0 +1,5 @@
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

49
ios/Runner/Info.plist Normal file
View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Logic Circuits Simulator</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>logic_circuits_simulator</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
</dict>
</plist>

View file

@ -0,0 +1 @@
#import "GeneratedPluginRegistrant.h"

View file

@ -0,0 +1,100 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:logic_circuits_simulator/state/projects.dart';
import 'package:logic_circuits_simulator/utils/provider_hook.dart';
class NewProjectDialog extends HookWidget {
const NewProjectDialog({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final projectsState = useProvider<ProjectsState>();
final newDialogNameController = useTextEditingController();
useListenable(newDialogNameController);
final newProjectAction = useMemoized(() {
if (newDialogNameController.text.isEmpty) return null;
return () {
projectsState.newProject(newDialogNameController.text);
Navigator.pop(context);
};
}, [newDialogNameController.text]);
return Center(
child: Card(
child: IntrinsicWidth(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: [
Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: OutlinedButton.icon(
onPressed: () {
// TODO: Implement project importing
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text('Import coming soon...'),
));
},
icon: const Icon(Icons.download),
label: const Text('Import Project'),
),
),
),
Row(
children: [
const Expanded(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Divider(),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Text(
'OR',
style: Theme.of(context).textTheme.caption,
),
),
const Expanded(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Divider(),
),
),
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'New Project',
style: Theme.of(context).textTheme.headline6,
textAlign: TextAlign.center,
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
constraints: const BoxConstraints(minWidth: 300),
child: TextField(
controller: newDialogNameController,
decoration: InputDecoration(
border: const OutlineInputBorder(),
labelText: 'Project name',
suffixIcon: IconButton(
icon: const Icon(Icons.done),
onPressed: newProjectAction,
),
),
onSubmitted: newProjectAction == null ? null : (_) => newProjectAction(),
),
),
),
],
),
),
),
);
}
}

106
lib/main.dart Normal file
View file

@ -0,0 +1,106 @@
import 'package:flutter/material.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:intl/intl_standalone.dart';
import 'package:logic_circuits_simulator/pages/edit_component.dart';
import 'package:logic_circuits_simulator/pages/project.dart';
import 'package:logic_circuits_simulator/pages/projects.dart';
import 'package:logic_circuits_simulator/pages/settings.dart';
import 'package:logic_circuits_simulator/pages_arguments/edit_component.dart';
import 'package:logic_circuits_simulator/state/project.dart';
import 'package:logic_circuits_simulator/state/projects.dart';
import 'package:provider/provider.dart';
Future<void> main() async {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: findSystemLocale().then((_) => initializeDateFormatting()).then((_) => true),
builder: (context, snapshot) {
if (!snapshot.hasData) {
// Wait until locale is detected
return Container();
}
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => ProjectsState()),
ChangeNotifierProvider(create: (_) => ProjectState()),
],
child: MaterialApp(
title: 'Logic Circuits Simulator',
theme: ThemeData(
useMaterial3: true,
primarySwatch: Colors.amber,
),
routes: {
ProjectsPage.routeName:(context) {
return const ProjectsPage();
},
MainPage.routeName:(context) {
return const MainPage();
},
SettingsPage.routeName:(context) => const SettingsPage(),
ProjectPage.routeName: (context) {
return const ProjectPage();
},
EditComponentPage.routeName: (context) {
final arguments = ModalRoute.of(context)!.settings.arguments as EditComponentPageArguments;
return EditComponentPage(
component: arguments.component,
newComponent: arguments.newComponent,
);
},
},
initialRoute: MainPage.routeName,
),
);
}
);
}
}
class MainPage extends StatelessWidget {
const MainPage({Key? key}) : super(key: key);
static const routeName = '/';
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Logic Circuits Simulator',
style: Theme.of(context).textTheme.headline3,
textAlign: TextAlign.center,
),
Column(
children: [
ElevatedButton.icon(
onPressed: () {
Navigator.of(context).pushNamed(ProjectsPage.routeName);
},
icon: const Icon(Icons.book),
label: const Text('Projects'),
),
ElevatedButton.icon(
onPressed: () {
Navigator.of(context).pushNamed(SettingsPage.routeName);
},
icon: const Icon(Icons.settings),
label: const Text('Settings'),
),
].map((e) => Padding(padding: const EdgeInsets.all(8), child: e,)).toList(growable: false),
)
],
),
),
);
}
}

29
lib/models/project.dart Normal file
View file

@ -0,0 +1,29 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'project.freezed.dart';
part 'project.g.dart';
@freezed
class ProjectIndex with _$ProjectIndex {
const factory ProjectIndex({
required List<ComponentEntry> components,
}) = _ProjectIndex;
factory ProjectIndex.fromJson(Map<String, Object?> json) => _$ProjectIndexFromJson(json);
}
@freezed
class ComponentEntry with _$ComponentEntry {
const factory ComponentEntry({
required String componentId,
required String componentName,
@JsonKey(includeIfNull: false)
String? componentDescription,
required List<String> inputs,
required List<String> outputs,
@JsonKey(includeIfNull: false)
List<String>? truthTable,
}) = _ComponentEntry;
factory ComponentEntry.fromJson(Map<String, Object?> json) => _$ComponentEntryFromJson(json);
}

View file

@ -0,0 +1,425 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
part of 'project.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
ProjectIndex _$ProjectIndexFromJson(Map<String, dynamic> json) {
return _ProjectIndex.fromJson(json);
}
/// @nodoc
mixin _$ProjectIndex {
List<ComponentEntry> get components => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$ProjectIndexCopyWith<ProjectIndex> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ProjectIndexCopyWith<$Res> {
factory $ProjectIndexCopyWith(
ProjectIndex value, $Res Function(ProjectIndex) then) =
_$ProjectIndexCopyWithImpl<$Res>;
$Res call({List<ComponentEntry> components});
}
/// @nodoc
class _$ProjectIndexCopyWithImpl<$Res> implements $ProjectIndexCopyWith<$Res> {
_$ProjectIndexCopyWithImpl(this._value, this._then);
final ProjectIndex _value;
// ignore: unused_field
final $Res Function(ProjectIndex) _then;
@override
$Res call({
Object? components = freezed,
}) {
return _then(_value.copyWith(
components: components == freezed
? _value.components
: components // ignore: cast_nullable_to_non_nullable
as List<ComponentEntry>,
));
}
}
/// @nodoc
abstract class _$$_ProjectIndexCopyWith<$Res>
implements $ProjectIndexCopyWith<$Res> {
factory _$$_ProjectIndexCopyWith(
_$_ProjectIndex value, $Res Function(_$_ProjectIndex) then) =
__$$_ProjectIndexCopyWithImpl<$Res>;
@override
$Res call({List<ComponentEntry> components});
}
/// @nodoc
class __$$_ProjectIndexCopyWithImpl<$Res>
extends _$ProjectIndexCopyWithImpl<$Res>
implements _$$_ProjectIndexCopyWith<$Res> {
__$$_ProjectIndexCopyWithImpl(
_$_ProjectIndex _value, $Res Function(_$_ProjectIndex) _then)
: super(_value, (v) => _then(v as _$_ProjectIndex));
@override
_$_ProjectIndex get _value => super._value as _$_ProjectIndex;
@override
$Res call({
Object? components = freezed,
}) {
return _then(_$_ProjectIndex(
components: components == freezed
? _value._components
: components // ignore: cast_nullable_to_non_nullable
as List<ComponentEntry>,
));
}
}
/// @nodoc
@JsonSerializable()
class _$_ProjectIndex implements _ProjectIndex {
const _$_ProjectIndex({required final List<ComponentEntry> components})
: _components = components;
factory _$_ProjectIndex.fromJson(Map<String, dynamic> json) =>
_$$_ProjectIndexFromJson(json);
final List<ComponentEntry> _components;
@override
List<ComponentEntry> get components {
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_components);
}
@override
String toString() {
return 'ProjectIndex(components: $components)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_ProjectIndex &&
const DeepCollectionEquality()
.equals(other._components, _components));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(
runtimeType, const DeepCollectionEquality().hash(_components));
@JsonKey(ignore: true)
@override
_$$_ProjectIndexCopyWith<_$_ProjectIndex> get copyWith =>
__$$_ProjectIndexCopyWithImpl<_$_ProjectIndex>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$_ProjectIndexToJson(this);
}
}
abstract class _ProjectIndex implements ProjectIndex {
const factory _ProjectIndex(
{required final List<ComponentEntry> components}) = _$_ProjectIndex;
factory _ProjectIndex.fromJson(Map<String, dynamic> json) =
_$_ProjectIndex.fromJson;
@override
List<ComponentEntry> get components => throw _privateConstructorUsedError;
@override
@JsonKey(ignore: true)
_$$_ProjectIndexCopyWith<_$_ProjectIndex> get copyWith =>
throw _privateConstructorUsedError;
}
ComponentEntry _$ComponentEntryFromJson(Map<String, dynamic> json) {
return _ComponentEntry.fromJson(json);
}
/// @nodoc
mixin _$ComponentEntry {
String get componentId => throw _privateConstructorUsedError;
String get componentName => throw _privateConstructorUsedError;
@JsonKey(includeIfNull: false)
String? get componentDescription => throw _privateConstructorUsedError;
List<String> get inputs => throw _privateConstructorUsedError;
List<String> get outputs => throw _privateConstructorUsedError;
@JsonKey(includeIfNull: false)
List<String>? get truthTable => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$ComponentEntryCopyWith<ComponentEntry> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ComponentEntryCopyWith<$Res> {
factory $ComponentEntryCopyWith(
ComponentEntry value, $Res Function(ComponentEntry) then) =
_$ComponentEntryCopyWithImpl<$Res>;
$Res call(
{String componentId,
String componentName,
@JsonKey(includeIfNull: false) String? componentDescription,
List<String> inputs,
List<String> outputs,
@JsonKey(includeIfNull: false) List<String>? truthTable});
}
/// @nodoc
class _$ComponentEntryCopyWithImpl<$Res>
implements $ComponentEntryCopyWith<$Res> {
_$ComponentEntryCopyWithImpl(this._value, this._then);
final ComponentEntry _value;
// ignore: unused_field
final $Res Function(ComponentEntry) _then;
@override
$Res call({
Object? componentId = freezed,
Object? componentName = freezed,
Object? componentDescription = freezed,
Object? inputs = freezed,
Object? outputs = freezed,
Object? truthTable = freezed,
}) {
return _then(_value.copyWith(
componentId: componentId == freezed
? _value.componentId
: componentId // ignore: cast_nullable_to_non_nullable
as String,
componentName: componentName == freezed
? _value.componentName
: componentName // ignore: cast_nullable_to_non_nullable
as String,
componentDescription: componentDescription == freezed
? _value.componentDescription
: componentDescription // ignore: cast_nullable_to_non_nullable
as String?,
inputs: inputs == freezed
? _value.inputs
: inputs // ignore: cast_nullable_to_non_nullable
as List<String>,
outputs: outputs == freezed
? _value.outputs
: outputs // ignore: cast_nullable_to_non_nullable
as List<String>,
truthTable: truthTable == freezed
? _value.truthTable
: truthTable // ignore: cast_nullable_to_non_nullable
as List<String>?,
));
}
}
/// @nodoc
abstract class _$$_ComponentEntryCopyWith<$Res>
implements $ComponentEntryCopyWith<$Res> {
factory _$$_ComponentEntryCopyWith(
_$_ComponentEntry value, $Res Function(_$_ComponentEntry) then) =
__$$_ComponentEntryCopyWithImpl<$Res>;
@override
$Res call(
{String componentId,
String componentName,
@JsonKey(includeIfNull: false) String? componentDescription,
List<String> inputs,
List<String> outputs,
@JsonKey(includeIfNull: false) List<String>? truthTable});
}
/// @nodoc
class __$$_ComponentEntryCopyWithImpl<$Res>
extends _$ComponentEntryCopyWithImpl<$Res>
implements _$$_ComponentEntryCopyWith<$Res> {
__$$_ComponentEntryCopyWithImpl(
_$_ComponentEntry _value, $Res Function(_$_ComponentEntry) _then)
: super(_value, (v) => _then(v as _$_ComponentEntry));
@override
_$_ComponentEntry get _value => super._value as _$_ComponentEntry;
@override
$Res call({
Object? componentId = freezed,
Object? componentName = freezed,
Object? componentDescription = freezed,
Object? inputs = freezed,
Object? outputs = freezed,
Object? truthTable = freezed,
}) {
return _then(_$_ComponentEntry(
componentId: componentId == freezed
? _value.componentId
: componentId // ignore: cast_nullable_to_non_nullable
as String,
componentName: componentName == freezed
? _value.componentName
: componentName // ignore: cast_nullable_to_non_nullable
as String,
componentDescription: componentDescription == freezed
? _value.componentDescription
: componentDescription // ignore: cast_nullable_to_non_nullable
as String?,
inputs: inputs == freezed
? _value._inputs
: inputs // ignore: cast_nullable_to_non_nullable
as List<String>,
outputs: outputs == freezed
? _value._outputs
: outputs // ignore: cast_nullable_to_non_nullable
as List<String>,
truthTable: truthTable == freezed
? _value._truthTable
: truthTable // ignore: cast_nullable_to_non_nullable
as List<String>?,
));
}
}
/// @nodoc
@JsonSerializable()
class _$_ComponentEntry implements _ComponentEntry {
const _$_ComponentEntry(
{required this.componentId,
required this.componentName,
@JsonKey(includeIfNull: false) this.componentDescription,
required final List<String> inputs,
required final List<String> outputs,
@JsonKey(includeIfNull: false) final List<String>? truthTable})
: _inputs = inputs,
_outputs = outputs,
_truthTable = truthTable;
factory _$_ComponentEntry.fromJson(Map<String, dynamic> json) =>
_$$_ComponentEntryFromJson(json);
@override
final String componentId;
@override
final String componentName;
@override
@JsonKey(includeIfNull: false)
final String? componentDescription;
final List<String> _inputs;
@override
List<String> get inputs {
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_inputs);
}
final List<String> _outputs;
@override
List<String> get outputs {
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_outputs);
}
final List<String>? _truthTable;
@override
@JsonKey(includeIfNull: false)
List<String>? get truthTable {
final value = _truthTable;
if (value == null) return null;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(value);
}
@override
String toString() {
return 'ComponentEntry(componentId: $componentId, componentName: $componentName, componentDescription: $componentDescription, inputs: $inputs, outputs: $outputs, truthTable: $truthTable)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_ComponentEntry &&
const DeepCollectionEquality()
.equals(other.componentId, componentId) &&
const DeepCollectionEquality()
.equals(other.componentName, componentName) &&
const DeepCollectionEquality()
.equals(other.componentDescription, componentDescription) &&
const DeepCollectionEquality().equals(other._inputs, _inputs) &&
const DeepCollectionEquality().equals(other._outputs, _outputs) &&
const DeepCollectionEquality()
.equals(other._truthTable, _truthTable));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(
runtimeType,
const DeepCollectionEquality().hash(componentId),
const DeepCollectionEquality().hash(componentName),
const DeepCollectionEquality().hash(componentDescription),
const DeepCollectionEquality().hash(_inputs),
const DeepCollectionEquality().hash(_outputs),
const DeepCollectionEquality().hash(_truthTable));
@JsonKey(ignore: true)
@override
_$$_ComponentEntryCopyWith<_$_ComponentEntry> get copyWith =>
__$$_ComponentEntryCopyWithImpl<_$_ComponentEntry>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$_ComponentEntryToJson(this);
}
}
abstract class _ComponentEntry implements ComponentEntry {
const factory _ComponentEntry(
{required final String componentId,
required final String componentName,
@JsonKey(includeIfNull: false) final String? componentDescription,
required final List<String> inputs,
required final List<String> outputs,
@JsonKey(includeIfNull: false) final List<String>? truthTable}) =
_$_ComponentEntry;
factory _ComponentEntry.fromJson(Map<String, dynamic> json) =
_$_ComponentEntry.fromJson;
@override
String get componentId => throw _privateConstructorUsedError;
@override
String get componentName => throw _privateConstructorUsedError;
@override
@JsonKey(includeIfNull: false)
String? get componentDescription => throw _privateConstructorUsedError;
@override
List<String> get inputs => throw _privateConstructorUsedError;
@override
List<String> get outputs => throw _privateConstructorUsedError;
@override
@JsonKey(includeIfNull: false)
List<String>? get truthTable => throw _privateConstructorUsedError;
@override
@JsonKey(ignore: true)
_$$_ComponentEntryCopyWith<_$_ComponentEntry> get copyWith =>
throw _privateConstructorUsedError;
}

52
lib/models/project.g.dart Normal file
View file

@ -0,0 +1,52 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'project.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$_ProjectIndex _$$_ProjectIndexFromJson(Map<String, dynamic> json) =>
_$_ProjectIndex(
components: (json['components'] as List<dynamic>)
.map((e) => ComponentEntry.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$$_ProjectIndexToJson(_$_ProjectIndex instance) =>
<String, dynamic>{
'components': instance.components,
};
_$_ComponentEntry _$$_ComponentEntryFromJson(Map<String, dynamic> json) =>
_$_ComponentEntry(
componentId: json['componentId'] as String,
componentName: json['componentName'] as String,
componentDescription: json['componentDescription'] as String?,
inputs:
(json['inputs'] as List<dynamic>).map((e) => e as String).toList(),
outputs:
(json['outputs'] as List<dynamic>).map((e) => e as String).toList(),
truthTable: (json['truthTable'] as List<dynamic>?)
?.map((e) => e as String)
.toList(),
);
Map<String, dynamic> _$$_ComponentEntryToJson(_$_ComponentEntry instance) {
final val = <String, dynamic>{
'componentId': instance.componentId,
'componentName': instance.componentName,
};
void writeNotNull(String key, dynamic value) {
if (value != null) {
val[key] = value;
}
}
writeNotNull('componentDescription', instance.componentDescription);
val['inputs'] = instance.inputs;
val['outputs'] = instance.outputs;
writeNotNull('truthTable', instance.truthTable);
return val;
}

24
lib/models/projects.dart Normal file
View file

@ -0,0 +1,24 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'projects.freezed.dart';
part 'projects.g.dart';
@freezed
class ProjectsIndex with _$ProjectsIndex {
const factory ProjectsIndex({
required List<ProjectEntry> projects,
}) = _ProjectsIndex;
factory ProjectsIndex.fromJson(Map<String, Object?> json) => _$ProjectsIndexFromJson(json);
}
@freezed
class ProjectEntry with _$ProjectEntry {
const factory ProjectEntry({
required DateTime lastUpdate,
required String projectName,
required String projectId,
}) = _ProjectEntry;
factory ProjectEntry.fromJson(Map<String, Object?> json) => _$ProjectEntryFromJson(json);
}

View file

@ -0,0 +1,327 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
part of 'projects.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
ProjectsIndex _$ProjectsIndexFromJson(Map<String, dynamic> json) {
return _ProjectsIndex.fromJson(json);
}
/// @nodoc
mixin _$ProjectsIndex {
List<ProjectEntry> get projects => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$ProjectsIndexCopyWith<ProjectsIndex> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ProjectsIndexCopyWith<$Res> {
factory $ProjectsIndexCopyWith(
ProjectsIndex value, $Res Function(ProjectsIndex) then) =
_$ProjectsIndexCopyWithImpl<$Res>;
$Res call({List<ProjectEntry> projects});
}
/// @nodoc
class _$ProjectsIndexCopyWithImpl<$Res>
implements $ProjectsIndexCopyWith<$Res> {
_$ProjectsIndexCopyWithImpl(this._value, this._then);
final ProjectsIndex _value;
// ignore: unused_field
final $Res Function(ProjectsIndex) _then;
@override
$Res call({
Object? projects = freezed,
}) {
return _then(_value.copyWith(
projects: projects == freezed
? _value.projects
: projects // ignore: cast_nullable_to_non_nullable
as List<ProjectEntry>,
));
}
}
/// @nodoc
abstract class _$$_ProjectsIndexCopyWith<$Res>
implements $ProjectsIndexCopyWith<$Res> {
factory _$$_ProjectsIndexCopyWith(
_$_ProjectsIndex value, $Res Function(_$_ProjectsIndex) then) =
__$$_ProjectsIndexCopyWithImpl<$Res>;
@override
$Res call({List<ProjectEntry> projects});
}
/// @nodoc
class __$$_ProjectsIndexCopyWithImpl<$Res>
extends _$ProjectsIndexCopyWithImpl<$Res>
implements _$$_ProjectsIndexCopyWith<$Res> {
__$$_ProjectsIndexCopyWithImpl(
_$_ProjectsIndex _value, $Res Function(_$_ProjectsIndex) _then)
: super(_value, (v) => _then(v as _$_ProjectsIndex));
@override
_$_ProjectsIndex get _value => super._value as _$_ProjectsIndex;
@override
$Res call({
Object? projects = freezed,
}) {
return _then(_$_ProjectsIndex(
projects: projects == freezed
? _value._projects
: projects // ignore: cast_nullable_to_non_nullable
as List<ProjectEntry>,
));
}
}
/// @nodoc
@JsonSerializable()
class _$_ProjectsIndex implements _ProjectsIndex {
const _$_ProjectsIndex({required final List<ProjectEntry> projects})
: _projects = projects;
factory _$_ProjectsIndex.fromJson(Map<String, dynamic> json) =>
_$$_ProjectsIndexFromJson(json);
final List<ProjectEntry> _projects;
@override
List<ProjectEntry> get projects {
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_projects);
}
@override
String toString() {
return 'ProjectsIndex(projects: $projects)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_ProjectsIndex &&
const DeepCollectionEquality().equals(other._projects, _projects));
}
@JsonKey(ignore: true)
@override
int get hashCode =>
Object.hash(runtimeType, const DeepCollectionEquality().hash(_projects));
@JsonKey(ignore: true)
@override
_$$_ProjectsIndexCopyWith<_$_ProjectsIndex> get copyWith =>
__$$_ProjectsIndexCopyWithImpl<_$_ProjectsIndex>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$_ProjectsIndexToJson(this);
}
}
abstract class _ProjectsIndex implements ProjectsIndex {
const factory _ProjectsIndex({required final List<ProjectEntry> projects}) =
_$_ProjectsIndex;
factory _ProjectsIndex.fromJson(Map<String, dynamic> json) =
_$_ProjectsIndex.fromJson;
@override
List<ProjectEntry> get projects => throw _privateConstructorUsedError;
@override
@JsonKey(ignore: true)
_$$_ProjectsIndexCopyWith<_$_ProjectsIndex> get copyWith =>
throw _privateConstructorUsedError;
}
ProjectEntry _$ProjectEntryFromJson(Map<String, dynamic> json) {
return _ProjectEntry.fromJson(json);
}
/// @nodoc
mixin _$ProjectEntry {
DateTime get lastUpdate => throw _privateConstructorUsedError;
String get projectName => throw _privateConstructorUsedError;
String get projectId => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$ProjectEntryCopyWith<ProjectEntry> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ProjectEntryCopyWith<$Res> {
factory $ProjectEntryCopyWith(
ProjectEntry value, $Res Function(ProjectEntry) then) =
_$ProjectEntryCopyWithImpl<$Res>;
$Res call({DateTime lastUpdate, String projectName, String projectId});
}
/// @nodoc
class _$ProjectEntryCopyWithImpl<$Res> implements $ProjectEntryCopyWith<$Res> {
_$ProjectEntryCopyWithImpl(this._value, this._then);
final ProjectEntry _value;
// ignore: unused_field
final $Res Function(ProjectEntry) _then;
@override
$Res call({
Object? lastUpdate = freezed,
Object? projectName = freezed,
Object? projectId = freezed,
}) {
return _then(_value.copyWith(
lastUpdate: lastUpdate == freezed
? _value.lastUpdate
: lastUpdate // ignore: cast_nullable_to_non_nullable
as DateTime,
projectName: projectName == freezed
? _value.projectName
: projectName // ignore: cast_nullable_to_non_nullable
as String,
projectId: projectId == freezed
? _value.projectId
: projectId // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
abstract class _$$_ProjectEntryCopyWith<$Res>
implements $ProjectEntryCopyWith<$Res> {
factory _$$_ProjectEntryCopyWith(
_$_ProjectEntry value, $Res Function(_$_ProjectEntry) then) =
__$$_ProjectEntryCopyWithImpl<$Res>;
@override
$Res call({DateTime lastUpdate, String projectName, String projectId});
}
/// @nodoc
class __$$_ProjectEntryCopyWithImpl<$Res>
extends _$ProjectEntryCopyWithImpl<$Res>
implements _$$_ProjectEntryCopyWith<$Res> {
__$$_ProjectEntryCopyWithImpl(
_$_ProjectEntry _value, $Res Function(_$_ProjectEntry) _then)
: super(_value, (v) => _then(v as _$_ProjectEntry));
@override
_$_ProjectEntry get _value => super._value as _$_ProjectEntry;
@override
$Res call({
Object? lastUpdate = freezed,
Object? projectName = freezed,
Object? projectId = freezed,
}) {
return _then(_$_ProjectEntry(
lastUpdate: lastUpdate == freezed
? _value.lastUpdate
: lastUpdate // ignore: cast_nullable_to_non_nullable
as DateTime,
projectName: projectName == freezed
? _value.projectName
: projectName // ignore: cast_nullable_to_non_nullable
as String,
projectId: projectId == freezed
? _value.projectId
: projectId // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
@JsonSerializable()
class _$_ProjectEntry implements _ProjectEntry {
const _$_ProjectEntry(
{required this.lastUpdate,
required this.projectName,
required this.projectId});
factory _$_ProjectEntry.fromJson(Map<String, dynamic> json) =>
_$$_ProjectEntryFromJson(json);
@override
final DateTime lastUpdate;
@override
final String projectName;
@override
final String projectId;
@override
String toString() {
return 'ProjectEntry(lastUpdate: $lastUpdate, projectName: $projectName, projectId: $projectId)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_ProjectEntry &&
const DeepCollectionEquality()
.equals(other.lastUpdate, lastUpdate) &&
const DeepCollectionEquality()
.equals(other.projectName, projectName) &&
const DeepCollectionEquality().equals(other.projectId, projectId));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(
runtimeType,
const DeepCollectionEquality().hash(lastUpdate),
const DeepCollectionEquality().hash(projectName),
const DeepCollectionEquality().hash(projectId));
@JsonKey(ignore: true)
@override
_$$_ProjectEntryCopyWith<_$_ProjectEntry> get copyWith =>
__$$_ProjectEntryCopyWithImpl<_$_ProjectEntry>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$_ProjectEntryToJson(this);
}
}
abstract class _ProjectEntry implements ProjectEntry {
const factory _ProjectEntry(
{required final DateTime lastUpdate,
required final String projectName,
required final String projectId}) = _$_ProjectEntry;
factory _ProjectEntry.fromJson(Map<String, dynamic> json) =
_$_ProjectEntry.fromJson;
@override
DateTime get lastUpdate => throw _privateConstructorUsedError;
@override
String get projectName => throw _privateConstructorUsedError;
@override
String get projectId => throw _privateConstructorUsedError;
@override
@JsonKey(ignore: true)
_$$_ProjectEntryCopyWith<_$_ProjectEntry> get copyWith =>
throw _privateConstructorUsedError;
}

View file

@ -0,0 +1,33 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'projects.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$_ProjectsIndex _$$_ProjectsIndexFromJson(Map<String, dynamic> json) =>
_$_ProjectsIndex(
projects: (json['projects'] as List<dynamic>)
.map((e) => ProjectEntry.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$$_ProjectsIndexToJson(_$_ProjectsIndex instance) =>
<String, dynamic>{
'projects': instance.projects,
};
_$_ProjectEntry _$$_ProjectEntryFromJson(Map<String, dynamic> json) =>
_$_ProjectEntry(
lastUpdate: DateTime.parse(json['lastUpdate'] as String),
projectName: json['projectName'] as String,
projectId: json['projectId'] as String,
);
Map<String, dynamic> _$$_ProjectEntryToJson(_$_ProjectEntry instance) =>
<String, dynamic>{
'lastUpdate': instance.lastUpdate.toIso8601String(),
'projectName': instance.projectName,
'projectId': instance.projectId,
};

View file

@ -0,0 +1,185 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:logic_circuits_simulator/models/project.dart';
import 'package:logic_circuits_simulator/state/project.dart';
import 'package:logic_circuits_simulator/utils/provider_hook.dart';
class EditComponentPage extends HookWidget {
final bool newComponent;
final ComponentEntry component;
const EditComponentPage({Key? key, this.newComponent = false, required this.component}) : super(key: key);
static const String routeName = '/project/component/edit';
@override
Widget build(BuildContext context) {
final anySave = useState(false);
final projectState = useProvider<ProjectState>();
final ce = projectState.index.components.where((c) => c.componentId == component.componentId).first;
final componentNameEditingController = useTextEditingController(text: ce.componentName);
useValueListenable(componentNameEditingController);
final dirty = useMemoized(() {
if (componentNameEditingController.text.isEmpty) {
// Don't allow saving empty name
return false;
}
if (componentNameEditingController.text != ce.componentName) {
return true;
}
return false;
}, [componentNameEditingController.text, ce.componentName]);
return WillPopScope(
onWillPop: () async {
if (!dirty && !newComponent) {
return true;
} else if (!dirty && anySave.value) {
return true;
}
final dialogResult = await showDialog(
context: context,
builder: (context) {
return AlertDialog(
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('Cancel'),
),
ElevatedButton(
onPressed: () {
Navigator.of(context).pop(true);
},
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.red),
),
child: const Text('Discard'),
),
],
title: Text('Cancel ${newComponent ? 'Creation' : 'Editing'}'),
content: Text(newComponent ? 'A new component will not be created.' : 'Are you sure you want to discard the changes?'),
);
}
);
return dialogResult == true;
},
child: Scaffold(
appBar: AppBar(
title: Text(newComponent ? 'New Component' : 'Edit Component'),
centerTitle: true,
),
body: CustomScrollView(
slivers: [
SliverPadding(
padding: const EdgeInsets.all(8),
sliver: SliverToBoxAdapter(
child: TextField(
controller: componentNameEditingController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Component name',
),
),
),
),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Inputs',
style: Theme.of(context).textTheme.headline5,
),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, i) => ListTile(title: Text(ce.inputs[i]),),
childCount: ce.inputs.length,
),
),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Outputs',
style: Theme.of(context).textTheme.headline5,
),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, i) => ListTile(title: Text(ce.outputs[i]),),
childCount: ce.outputs.length,
),
),
if (ce.truthTable != null) ...[
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Truth Table',
style: Theme.of(context).textTheme.headline5,
),
),
),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TruthTableEditor(
truthTable: ce.truthTable!,
inputs: ce.inputs,
outputs: ce.outputs,
),
),
)
],
],
),
floatingActionButton: !dirty ? null : FloatingActionButton(
onPressed: () async {
if (componentNameEditingController.text.isNotEmpty) {
await projectState.editComponent(component.copyWith(componentName: componentNameEditingController.text));
}
anySave.value = true;
// TODO: Implement saving
},
tooltip: 'Save Component',
child: const Icon(Icons.save),
),
),
);
}
}
class TruthTableEditor extends StatelessWidget {
final List<String> inputs;
final List<String> outputs;
final List<String> truthTable;
const TruthTableEditor({Key? key, required this.inputs, required this.outputs, required this.truthTable}) : super(key: key);
@override
Widget build(BuildContext context) {
return Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: List.generate(
truthTable.length + 1,
(index) {
if (index == 0) {
return TableRow(
children: inputs.map((e) => Text(e)).followedBy(outputs.map((e) => Text(e))).toList(),
);
}
final inputBinary = (index - 1).toRadixString(2).padLeft(inputs.length, '0');
final outputBinary = truthTable[index - 1];
return TableRow(
children: inputBinary.runes.map((r) => Text(String.fromCharCodes([r])))
.followedBy(outputBinary.runes.map((r) => Text(String.fromCharCodes([r]))))
.toList(),
);
},
),
);
}
}

240
lib/pages/project.dart Normal file
View file

@ -0,0 +1,240 @@
import 'package:flutter/material.dart';
import 'package:logic_circuits_simulator/models/project.dart';
import 'package:logic_circuits_simulator/pages/edit_component.dart';
import 'package:logic_circuits_simulator/pages_arguments/edit_component.dart';
import 'package:logic_circuits_simulator/state/project.dart';
import 'package:provider/provider.dart';
class ProjectPage extends StatelessWidget {
const ProjectPage({Key? key}) : super(key: key);
static const String routeName = '/project';
void onComponentDelete(BuildContext context, ComponentEntry c) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('Cancel'),
),
ElevatedButton(
onPressed: () {
Provider.of<ProjectState>(context, listen: false)
.deleteComponent(c.componentId);
Navigator.of(context).pop();
},
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.red),
),
child: const Text('Delete'),
),
],
title: Text('Delete component ${c.componentName}'),
content: const Text('Are you sure you want to delete the component?'),
);
},
);
}
Future<bool> onComponentEdit(BuildContext context, ComponentEntry c, {bool newComponent = false}) {
return Navigator.of(context).pushNamed(
EditComponentPage.routeName,
arguments: EditComponentPageArguments(
component: c,
newComponent: newComponent,
),
).then((value) => value == true,);
}
void onComponentCreate(BuildContext context) async {
final newComponent = await Provider.of<ProjectState>(context, listen: false).newComponent();
// ignore: use_build_context_synchronously
if (!await onComponentEdit(context, newComponent, newComponent: true)) {
// ignore: use_build_context_synchronously
await Future.delayed(
const Duration(milliseconds: 500),
() => Provider.of<ProjectState>(context, listen: false)
.deleteComponent(newComponent.componentId),
);
}
}
@override
Widget build(BuildContext context) {
final project = Provider.of<ProjectState>(context).currentProject;
final index = Provider.of<ProjectState>(context).index;
return WillPopScope(
onWillPop: () async {
final ps = Provider.of<ProjectState>(context, listen: false);
if (ps.needsSaving) {
Future? saveFuture;
await showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
saveFuture ??= ps.saveProject().then((_) {
Navigator.of(context).pop();
});
return Center(
child: Card(
child: Row(
mainAxisSize: MainAxisSize.min,
children: const [
Padding(
padding: EdgeInsets.all(8.0),
child: CircularProgressIndicator(),
),
Padding(
padding: EdgeInsets.all(8.0),
child: Text('Saving...'),
)
],
),
),
);
},
);
}
ps.noProject();
return true;
},
child: Scaffold(
appBar: AppBar(
title: Text(project?.projectName ?? 'No Project'),
centerTitle: true,
),
body: project == null ? Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: [
Text(
'No project selected',
style: Theme.of(context).textTheme.headline4,
textAlign: TextAlign.center,
),
],
),
) : CustomScrollView(
slivers: [
SliverPadding(
padding: const EdgeInsets.all(8),
sliver: SliverToBoxAdapter(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Text(
'Components',
style: Theme.of(context).textTheme.headline5,
),
),
IconButton(
onPressed: () {
onComponentCreate(context);
},
icon: const Icon(Icons.add),
tooltip: 'New Component',
),
],
),
),
),
if (index.components.isNotEmpty)
SliverToBoxAdapter(
child: Wrap(
runSpacing: 8,
spacing: 8,
children: index.components.map((c) => IntrinsicWidth(
child: ComponentCard(
component: c,
onComponentDelete: () => onComponentDelete(context, c),
onComponentEdit: () => onComponentEdit(context, c),
),
)).toList(growable: false),
),
)
else
SliverToBoxAdapter(
child: Center(
child: Text(
'No Components',
style: Theme.of(context).textTheme.headline6,
),
),
),
],
),
),
);
}
}
class ComponentCard extends StatelessWidget {
final ComponentEntry component;
final void Function() onComponentDelete;
final void Function() onComponentEdit;
const ComponentCard({Key? key, required this.component, required this.onComponentDelete, required this.onComponentEdit}) : super(key: key);
@override
Widget build(BuildContext context) {
return Card(
child: InkWell(
onTap: () {
onComponentEdit();
},
child: Stack(
children: [
Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: Text(
component.componentName,
style: Theme.of(context).textTheme.headline6,
),
),
const SizedBox(width: 36,),
],
),
),
],
),
Positioned(
top: 8,
right: 8,
child: PopupMenuButton<String>(
icon: const Icon(Icons.more_horiz),
itemBuilder: (context) => [
const PopupMenuItem(
value: 'delete',
child: Text('Delete'),
),
],
onSelected: (selectedOption) {
switch (selectedOption) {
case 'delete':
onComponentDelete();
break;
default:
throw Exception('Unexpected option: $selectedOption');
}
},
),
),
],
),
),
);
}
}

204
lib/pages/projects.dart Normal file
View file

@ -0,0 +1,204 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:logic_circuits_simulator/dialogs/new_project.dart';
import 'package:logic_circuits_simulator/models/projects.dart';
import 'package:logic_circuits_simulator/pages/project.dart';
import 'package:logic_circuits_simulator/state/project.dart';
import 'package:logic_circuits_simulator/state/projects.dart';
import 'package:provider/provider.dart';
class ProjectsPage extends StatelessWidget {
const ProjectsPage({Key? key}) : super(key: key);
static const String routeName = '/projects';
void onNewProject(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return const NewProjectDialog();
},
);
}
void onProjectDelete(BuildContext context, ProjectEntry p) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('Cancel'),
),
ElevatedButton(
onPressed: () {
Provider.of<ProjectsState>(context, listen: false)
.deleteProject(p.projectId);
Navigator.of(context).pop();
},
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.red),
),
child: const Text('Delete'),
),
],
title: Text('Delete project ${p.projectName}'),
content: const Text('Are you sure you want to delete the project?'),
);
},
);
}
void onProjectSelect(BuildContext context, ProjectEntry p) {
Provider.of<ProjectState>(context, listen: false).currentProject = p;
Provider.of<ProjectState>(context, listen: false).registerSaveHandler((p) async {
await Provider.of<ProjectsState>(context, listen: false).updateProject(p);
});
Navigator.of(context).pushNamed(ProjectPage.routeName);
}
@override
Widget build(BuildContext context) {
final projects = Provider.of<ProjectsState>(context).projects;
return Scaffold(
appBar: AppBar(
title: const Text('Projects'),
centerTitle: true,
),
body: projects.isNotEmpty
? SingleChildScrollView(
child: Wrap(
runSpacing: 8,
spacing: 8,
children:
projects.map((p) => IntrinsicWidth(
child: ProjectTile(
p,
onProjectDelete: () => onProjectDelete(context, p),
onProjectExport: () {
// TODO: Implement project export
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Export coming soon...')));
},
onProjectSelect: () => onProjectSelect(context, p),
),
)).toList(growable: false),
),
)
: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: [
Text(
'No projects',
style: Theme.of(context).textTheme.headline4,
textAlign: TextAlign.center,
),
const Text.rich(
TextSpan(
children: [
TextSpan(text: 'Use the '),
WidgetSpan(
child: Icon(
Icons.add,
size: 16,
)),
TextSpan(text: ' button to add a new project.'),
],
),
textAlign: TextAlign.center,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => onNewProject(context),
tooltip: 'New Project',
child: const Icon(Icons.add),
),
);
}
}
class ProjectTile extends StatelessWidget {
final ProjectEntry project;
final void Function() onProjectSelect;
final void Function() onProjectDelete;
final void Function() onProjectExport;
const ProjectTile(this.project,
{Key? key, required this.onProjectSelect, required this.onProjectDelete, required this.onProjectExport})
: super(key: key);
@override
Widget build(BuildContext context) {
return Card(
child: InkWell(
onTap: onProjectSelect,
child: Stack(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child: Text(
project.projectName,
style: Theme.of(context).textTheme.headline6,
),
),
const SizedBox(width: 36,),
],
),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: Text(
DateFormat.yMMMd().add_jms().format(project.lastUpdate.toLocal()),
style: Theme.of(context).textTheme.caption,
textAlign: TextAlign.end,
),
),
],
),
Positioned(
top: 8,
right: 8,
child: PopupMenuButton<String>(
icon: const Icon(Icons.more_horiz),
itemBuilder: (context) => [
const PopupMenuItem(
value: 'export',
child: Text('Export'),
),
const PopupMenuItem(
value: 'delete',
child: Text('Delete'),
),
],
onSelected: (selectedOption) {
switch (selectedOption) {
case 'delete':
onProjectDelete();
break;
case 'export':
onProjectExport();
break;
default:
throw Exception('Unexpected option: $selectedOption');
}
},
),
),
],
),
),
);
}
}

17
lib/pages/settings.dart Normal file
View file

@ -0,0 +1,17 @@
import 'package:flutter/material.dart';
class SettingsPage extends StatelessWidget {
const SettingsPage({Key? key}) : super(key: key);
static const String routeName = '/settings';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Settings'),
centerTitle: true,
),
);
}
}

View file

@ -0,0 +1,13 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:logic_circuits_simulator/models/project.dart';
part 'edit_component.freezed.dart';
@freezed
class EditComponentPageArguments with _$EditComponentPageArguments {
const factory EditComponentPageArguments({
required ComponentEntry component,
@Default(false)
bool newComponent,
}) = _EditComponentPageArguments;
}

View file

@ -0,0 +1,170 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
part of 'edit_component.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
/// @nodoc
mixin _$EditComponentPageArguments {
ComponentEntry get component => throw _privateConstructorUsedError;
bool get newComponent => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$EditComponentPageArgumentsCopyWith<EditComponentPageArguments>
get copyWith => throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $EditComponentPageArgumentsCopyWith<$Res> {
factory $EditComponentPageArgumentsCopyWith(EditComponentPageArguments value,
$Res Function(EditComponentPageArguments) then) =
_$EditComponentPageArgumentsCopyWithImpl<$Res>;
$Res call({ComponentEntry component, bool newComponent});
$ComponentEntryCopyWith<$Res> get component;
}
/// @nodoc
class _$EditComponentPageArgumentsCopyWithImpl<$Res>
implements $EditComponentPageArgumentsCopyWith<$Res> {
_$EditComponentPageArgumentsCopyWithImpl(this._value, this._then);
final EditComponentPageArguments _value;
// ignore: unused_field
final $Res Function(EditComponentPageArguments) _then;
@override
$Res call({
Object? component = freezed,
Object? newComponent = freezed,
}) {
return _then(_value.copyWith(
component: component == freezed
? _value.component
: component // ignore: cast_nullable_to_non_nullable
as ComponentEntry,
newComponent: newComponent == freezed
? _value.newComponent
: newComponent // ignore: cast_nullable_to_non_nullable
as bool,
));
}
@override
$ComponentEntryCopyWith<$Res> get component {
return $ComponentEntryCopyWith<$Res>(_value.component, (value) {
return _then(_value.copyWith(component: value));
});
}
}
/// @nodoc
abstract class _$$_EditComponentPageArgumentsCopyWith<$Res>
implements $EditComponentPageArgumentsCopyWith<$Res> {
factory _$$_EditComponentPageArgumentsCopyWith(
_$_EditComponentPageArguments value,
$Res Function(_$_EditComponentPageArguments) then) =
__$$_EditComponentPageArgumentsCopyWithImpl<$Res>;
@override
$Res call({ComponentEntry component, bool newComponent});
@override
$ComponentEntryCopyWith<$Res> get component;
}
/// @nodoc
class __$$_EditComponentPageArgumentsCopyWithImpl<$Res>
extends _$EditComponentPageArgumentsCopyWithImpl<$Res>
implements _$$_EditComponentPageArgumentsCopyWith<$Res> {
__$$_EditComponentPageArgumentsCopyWithImpl(
_$_EditComponentPageArguments _value,
$Res Function(_$_EditComponentPageArguments) _then)
: super(_value, (v) => _then(v as _$_EditComponentPageArguments));
@override
_$_EditComponentPageArguments get _value =>
super._value as _$_EditComponentPageArguments;
@override
$Res call({
Object? component = freezed,
Object? newComponent = freezed,
}) {
return _then(_$_EditComponentPageArguments(
component: component == freezed
? _value.component
: component // ignore: cast_nullable_to_non_nullable
as ComponentEntry,
newComponent: newComponent == freezed
? _value.newComponent
: newComponent // ignore: cast_nullable_to_non_nullable
as bool,
));
}
}
/// @nodoc
class _$_EditComponentPageArguments implements _EditComponentPageArguments {
const _$_EditComponentPageArguments(
{required this.component, this.newComponent = false});
@override
final ComponentEntry component;
@override
@JsonKey()
final bool newComponent;
@override
String toString() {
return 'EditComponentPageArguments(component: $component, newComponent: $newComponent)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_EditComponentPageArguments &&
const DeepCollectionEquality().equals(other.component, component) &&
const DeepCollectionEquality()
.equals(other.newComponent, newComponent));
}
@override
int get hashCode => Object.hash(
runtimeType,
const DeepCollectionEquality().hash(component),
const DeepCollectionEquality().hash(newComponent));
@JsonKey(ignore: true)
@override
_$$_EditComponentPageArgumentsCopyWith<_$_EditComponentPageArguments>
get copyWith => __$$_EditComponentPageArgumentsCopyWithImpl<
_$_EditComponentPageArguments>(this, _$identity);
}
abstract class _EditComponentPageArguments
implements EditComponentPageArguments {
const factory _EditComponentPageArguments(
{required final ComponentEntry component,
final bool newComponent}) = _$_EditComponentPageArguments;
@override
ComponentEntry get component => throw _privateConstructorUsedError;
@override
bool get newComponent => throw _privateConstructorUsedError;
@override
@JsonKey(ignore: true)
_$$_EditComponentPageArgumentsCopyWith<_$_EditComponentPageArguments>
get copyWith => throw _privateConstructorUsedError;
}

109
lib/state/project.dart Normal file
View file

@ -0,0 +1,109 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:logic_circuits_simulator/models/project.dart';
import 'package:logic_circuits_simulator/models/projects.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as path;
import 'package:uuid/uuid.dart';
class ProjectState extends ChangeNotifier {
bool _dirty = false;
final List<Future Function(ProjectEntry)> _saveHandlers = [];
ProjectEntry? _currentProject;
ProjectIndex _index = const ProjectIndex(components: []);
ProjectEntry? get currentProject => _currentProject;
ProjectIndex get index => _index;
bool get needsSaving => currentProject != null && _dirty;
Future<Directory> _getProjectDir() async {
if (_currentProject == null) {
throw Exception('Cannot get project directory of null');
}
final appDir = await getApplicationDocumentsDirectory();
final result = Directory(path.join(appDir.path, 'LogicCircuitsSimulator', 'projects', _currentProject!.projectId));
if (!await result.exists()) {
await result.create(recursive: true);
}
return result;
}
Future<File> _getIndexFile() async {
final result = File(path.join((await _getProjectDir()).path, 'index.json'));
return result;
}
Future<void> _loadProjectFiles() async {
final indexFile = await _getIndexFile();
if (!await indexFile.exists()) {
_index = const ProjectIndex(components: []);
await indexFile.writeAsString(jsonEncode(_index.toJson()));
}
else {
_index = ProjectIndex.fromJson(jsonDecode(await indexFile.readAsString()));
}
}
Future<void> _updateIndex(ProjectIndex newIndex) async {
_dirty = true;
_index = newIndex;
final indexFile = await _getIndexFile();
await indexFile.writeAsString(jsonEncode(index.toJson()));
notifyListeners();
}
set currentProject(ProjectEntry? p) {
_currentProject = p;
_loadProjectFiles().then((_) => notifyListeners());
}
void noProject() {
_currentProject = null;
_index = const ProjectIndex(components: []);
notifyListeners();
}
Future<void> deleteComponent(String componentId) async {
await _updateIndex(index.copyWith(components: index.components.where((c) => c.componentId != componentId).toList()));
}
Future<ComponentEntry> newComponent() async {
final newComponent = ComponentEntry(
componentId: const Uuid().v4(),
componentName: '',
inputs: [],
outputs: [],
);
await _updateIndex(index.copyWith(components: index.components + [newComponent]));
return newComponent;
}
Future<void> editComponent(ComponentEntry component) async {
if (!index.components.map((c) => c.componentId).contains(component.componentId)) {
throw Exception('Component not in index!');
}
await _updateIndex(
index.copyWith(
components: index.components
.where((c) => c.componentId != component.componentId)
.toList() + [component],
)
);
}
Future<void> saveProject() async {
if (!needsSaving) return;
_currentProject = currentProject?.copyWith(lastUpdate: DateTime.now());
await Future.wait(_saveHandlers.map((h) => h(_currentProject!)));
_saveHandlers.clear();
_dirty = false;
notifyListeners();
}
void registerSaveHandler(Future Function(ProjectEntry) handler) {
_saveHandlers.add(handler);
}
}

80
lib/state/projects.dart Normal file
View file

@ -0,0 +1,80 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:logic_circuits_simulator/models/projects.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as path;
import 'package:uuid/uuid.dart';
class ProjectsState extends ChangeNotifier {
ProjectsState() {
_init();
}
List<ProjectEntry> get projects => index.projects;
ProjectsIndex index = const ProjectsIndex(projects: []);
Future<Directory> _getProjectsDir() async {
final appDir = await getApplicationDocumentsDirectory();
final result = Directory(path.join(appDir.path, 'LogicCircuitsSimulator', 'projects'));
if (!await result.exists()) {
await result.create(recursive: true);
}
return result;
}
Future<File> _getIndexFile() async {
final result = File(path.join((await _getProjectsDir()).path, 'index.json'));
return result;
}
Future<void> _updateIndex(ProjectsIndex newIndex) async {
// Sort projects when updating: latest update first
index = newIndex.copyWith(projects: newIndex.projects.toList()..sort((p1, p2) => p2.lastUpdate.compareTo(p1.lastUpdate)));
final indexFile = await _getIndexFile();
await indexFile.writeAsString(jsonEncode(index.toJson()));
notifyListeners();
}
void _init() async {
final indexFile = await _getIndexFile();
if (await indexFile.exists()) {
index = ProjectsIndex.fromJson(jsonDecode(await indexFile.readAsString()));
notifyListeners();
}
}
Future<void> newProject(String projectName) async {
final id = const Uuid().v4();
final project = ProjectEntry(
lastUpdate: DateTime.now(),
projectName: projectName,
projectId: id,
);
await _updateIndex(index.copyWith(projects: index.projects + [project]));
final projectDir = await Directory(path.join((await _getProjectsDir()).path, id)).create();
await Directory(path.join(projectDir.path, 'components')).create();
if (kDebugMode) {
print('Created new project in ${projectDir.path}');
}
}
Future<void> deleteProject(String projectId) async {
await _updateIndex(index.copyWith(projects: index.projects.where((p) => p.projectId != projectId).toList()));
await Directory(path.join((await _getProjectsDir()).path, projectId)).delete(recursive: true);
}
Future<void> updateProject(ProjectEntry project) async {
if (!index.projects.map((p) => p.projectId).contains(project.projectId)) {
throw Exception('Project not in index!');
}
await _updateIndex(
index.copyWith(
projects: index.projects
.where((p) => p.projectId != project.projectId)
.toList() + [project]
)
);
}
}

View file

@ -0,0 +1,7 @@
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:provider/provider.dart';
T useProvider<T>() {
final context = useContext();
return Provider.of<T>(context);
}

1
linux/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
flutter/ephemeral

138
linux/CMakeLists.txt Normal file
View file

@ -0,0 +1,138 @@
# Project-level configuration.
cmake_minimum_required(VERSION 3.10)
project(runner LANGUAGES CXX)
# The name of the executable created for the application. Change this to change
# the on-disk name of your application.
set(BINARY_NAME "logic_circuits_simulator")
# The unique GTK application identifier for this application. See:
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
set(APPLICATION_ID "ro.dcdev.logic_circuits_simulator")
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
# versions of CMake.
cmake_policy(SET CMP0063 NEW)
# Load bundled libraries from the lib/ directory relative to the binary.
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
# Root filesystem for cross-building.
if(FLUTTER_TARGET_PLATFORM_SYSROOT)
set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
endif()
# Define build configuration options.
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE "Debug" CACHE
STRING "Flutter build mode" FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Profile" "Release")
endif()
# Compilation settings that should be applied to most targets.
#
# Be cautious about adding new options here, as plugins use this function by
# default. In most cases, you should add new options to specific targets instead
# of modifying this function.
function(APPLY_STANDARD_SETTINGS TARGET)
target_compile_features(${TARGET} PUBLIC cxx_std_14)
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
endfunction()
# Flutter library and tool build rules.
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
add_subdirectory(${FLUTTER_MANAGED_DIR})
# System-level dependencies.
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
# Define the application target. To change its name, change BINARY_NAME above,
# not the value here, or `flutter run` will no longer work.
#
# Any new source files that you add to the application should be added here.
add_executable(${BINARY_NAME}
"main.cc"
"my_application.cc"
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
)
# Apply the standard set of build settings. This can be removed for applications
# that need different build settings.
apply_standard_settings(${BINARY_NAME})
# Add dependency libraries. Add any application-specific dependencies here.
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
# Run the Flutter tool portions of the build. This must not be removed.
add_dependencies(${BINARY_NAME} flutter_assemble)
# Only the install-generated bundle's copy of the executable will launch
# correctly, since the resources must in the right relative locations. To avoid
# people trying to run the unbundled copy, put it in a subdirectory instead of
# the default top-level location.
set_target_properties(${BINARY_NAME}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
)
# Generated plugin build rules, which manage building the plugins and adding
# them to the application.
include(flutter/generated_plugins.cmake)
# === Installation ===
# By default, "installing" just makes a relocatable bundle in the build
# directory.
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
endif()
# Start with a clean build bundle directory every time.
install(CODE "
file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
" COMPONENT Runtime)
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
COMPONENT Runtime)
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
COMPONENT Runtime)
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
install(FILES "${bundled_library}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
endforeach(bundled_library)
# Fully re-copy the assets directory on each build to avoid having stale files
# from a previous install.
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
install(CODE "
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
" COMPONENT Runtime)
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
# Install the AOT library on non-Debug builds only.
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
endif()

View file

@ -0,0 +1,88 @@
# This file controls Flutter-level build steps. It should not be edited.
cmake_minimum_required(VERSION 3.10)
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
# Configuration provided via flutter tool.
include(${EPHEMERAL_DIR}/generated_config.cmake)
# TODO: Move the rest of this into files in ephemeral. See
# https://github.com/flutter/flutter/issues/57146.
# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
# which isn't available in 3.10.
function(list_prepend LIST_NAME PREFIX)
set(NEW_LIST "")
foreach(element ${${LIST_NAME}})
list(APPEND NEW_LIST "${PREFIX}${element}")
endforeach(element)
set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
endfunction()
# === Flutter Library ===
# System-level dependencies.
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
# Published to parent scope for install step.
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
list(APPEND FLUTTER_LIBRARY_HEADERS
"fl_basic_message_channel.h"
"fl_binary_codec.h"
"fl_binary_messenger.h"
"fl_dart_project.h"
"fl_engine.h"
"fl_json_message_codec.h"
"fl_json_method_codec.h"
"fl_message_codec.h"
"fl_method_call.h"
"fl_method_channel.h"
"fl_method_codec.h"
"fl_method_response.h"
"fl_plugin_registrar.h"
"fl_plugin_registry.h"
"fl_standard_message_codec.h"
"fl_standard_method_codec.h"
"fl_string_codec.h"
"fl_value.h"
"fl_view.h"
"flutter_linux.h"
)
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
add_library(flutter INTERFACE)
target_include_directories(flutter INTERFACE
"${EPHEMERAL_DIR}"
)
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
target_link_libraries(flutter INTERFACE
PkgConfig::GTK
PkgConfig::GLIB
PkgConfig::GIO
)
add_dependencies(flutter flutter_assemble)
# === Flutter tool backend ===
# _phony_ is a non-existent file to force this command to run every time,
# since currently there's no way to get a full input/output list from the
# flutter tool.
add_custom_command(
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
${CMAKE_CURRENT_BINARY_DIR}/_phony_
COMMAND ${CMAKE_COMMAND} -E env
${FLUTTER_TOOL_ENVIRONMENT}
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
VERBATIM
)
add_custom_target(flutter_assemble DEPENDS
"${FLUTTER_LIBRARY}"
${FLUTTER_LIBRARY_HEADERS}
)

View file

@ -0,0 +1,11 @@
//
// Generated file. Do not edit.
//
// clang-format off
#include "generated_plugin_registrant.h"
void fl_register_plugins(FlPluginRegistry* registry) {
}

View file

@ -0,0 +1,15 @@
//
// Generated file. Do not edit.
//
// clang-format off
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_
#include <flutter_linux/flutter_linux.h>
// Registers Flutter plugins.
void fl_register_plugins(FlPluginRegistry* registry);
#endif // GENERATED_PLUGIN_REGISTRANT_

View file

@ -0,0 +1,23 @@
#
# Generated file, do not edit.
#
list(APPEND FLUTTER_PLUGIN_LIST
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
)
set(PLUGIN_BUNDLED_LIBRARIES)
foreach(plugin ${FLUTTER_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
endforeach(ffi_plugin)

6
linux/main.cc Normal file
View file

@ -0,0 +1,6 @@
#include "my_application.h"
int main(int argc, char** argv) {
g_autoptr(MyApplication) app = my_application_new();
return g_application_run(G_APPLICATION(app), argc, argv);
}

104
linux/my_application.cc Normal file
View file

@ -0,0 +1,104 @@
#include "my_application.h"
#include <flutter_linux/flutter_linux.h>
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
#include "flutter/generated_plugin_registrant.h"
struct _MyApplication {
GtkApplication parent_instance;
char** dart_entrypoint_arguments;
};
G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
// Implements GApplication::activate.
static void my_application_activate(GApplication* application) {
MyApplication* self = MY_APPLICATION(application);
GtkWindow* window =
GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
// Use a header bar when running in GNOME as this is the common style used
// by applications and is the setup most users will be using (e.g. Ubuntu
// desktop).
// If running on X and not using GNOME then just use a traditional title bar
// in case the window manager does more exotic layout, e.g. tiling.
// If running on Wayland assume the header bar will work (may need changing
// if future cases occur).
gboolean use_header_bar = TRUE;
#ifdef GDK_WINDOWING_X11
GdkScreen* screen = gtk_window_get_screen(window);
if (GDK_IS_X11_SCREEN(screen)) {
const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
use_header_bar = FALSE;
}
}
#endif
if (use_header_bar) {
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
gtk_widget_show(GTK_WIDGET(header_bar));
gtk_header_bar_set_title(header_bar, "logic_circuits_simulator");
gtk_header_bar_set_show_close_button(header_bar, TRUE);
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
} else {
gtk_window_set_title(window, "logic_circuits_simulator");
}
gtk_window_set_default_size(window, 1280, 720);
gtk_widget_show(GTK_WIDGET(window));
g_autoptr(FlDartProject) project = fl_dart_project_new();
fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
FlView* view = fl_view_new(project);
gtk_widget_show(GTK_WIDGET(view));
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
fl_register_plugins(FL_PLUGIN_REGISTRY(view));
gtk_widget_grab_focus(GTK_WIDGET(view));
}
// Implements GApplication::local_command_line.
static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
MyApplication* self = MY_APPLICATION(application);
// Strip out the first argument as it is the binary name.
self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
g_autoptr(GError) error = nullptr;
if (!g_application_register(application, nullptr, &error)) {
g_warning("Failed to register: %s", error->message);
*exit_status = 1;
return TRUE;
}
g_application_activate(application);
*exit_status = 0;
return TRUE;
}
// Implements GObject::dispose.
static void my_application_dispose(GObject* object) {
MyApplication* self = MY_APPLICATION(object);
g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
}
static void my_application_class_init(MyApplicationClass* klass) {
G_APPLICATION_CLASS(klass)->activate = my_application_activate;
G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
}
static void my_application_init(MyApplication* self) {}
MyApplication* my_application_new() {
return MY_APPLICATION(g_object_new(my_application_get_type(),
"application-id", APPLICATION_ID,
"flags", G_APPLICATION_NON_UNIQUE,
nullptr));
}

18
linux/my_application.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef FLUTTER_MY_APPLICATION_H_
#define FLUTTER_MY_APPLICATION_H_
#include <gtk/gtk.h>
G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
GtkApplication)
/**
* my_application_new:
*
* Creates a new Flutter-based application.
*
* Returns: a new #MyApplication.
*/
MyApplication* my_application_new();
#endif // FLUTTER_MY_APPLICATION_H_

670
pubspec.lock Normal file
View file

@ -0,0 +1,670 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
_fe_analyzer_shared:
dependency: transitive
description:
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
version: "39.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
args:
dependency: transitive
description:
name: args
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.0"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.2"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
build:
dependency: transitive
description:
name: build
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.0"
build_config:
dependency: transitive
description:
name: build_config
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
build_daemon:
dependency: transitive
description:
name: build_daemon
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.0"
build_resolvers:
dependency: transitive
description:
name: build_resolvers
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.8"
build_runner:
dependency: "direct dev"
description:
name: build_runner
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.10"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
url: "https://pub.dartlang.org"
source: hosted
version: "7.2.3"
built_collection:
dependency: transitive
description:
name: built_collection
url: "https://pub.dartlang.org"
source: hosted
version: "5.1.1"
built_value:
dependency: transitive
description:
name: built_value
url: "https://pub.dartlang.org"
source: hosted
version: "8.2.3"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
checked_yaml:
dependency: transitive
description:
name: checked_yaml
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
code_builder:
dependency: transitive
description:
name: code_builder
url: "https://pub.dartlang.org"
source: hosted
version: "4.1.0"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.16.0"
convert:
dependency: transitive
description:
name: convert
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.2"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
dart_style:
dependency: transitive
description:
name: dart_style
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.3"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
ffi:
dependency: transitive
description:
name: ffi
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.2"
file:
dependency: transitive
description:
name: file
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.2"
fixnum:
dependency: transitive
description:
name: fixnum
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_hooks:
dependency: "direct main"
description:
name: flutter_hooks
url: "https://pub.dartlang.org"
source: hosted
version: "0.18.3"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
freezed:
dependency: "direct main"
description:
name: freezed
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
freezed_annotation:
dependency: "direct main"
description:
name: freezed_annotation
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
glob:
dependency: transitive
description:
name: glob
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
graphs:
dependency: transitive
description:
name: graphs
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
http_multi_server:
dependency: transitive
description:
name: http_multi_server
url: "https://pub.dartlang.org"
source: hosted
version: "3.2.0"
http_parser:
dependency: transitive
description:
name: http_parser
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
intl:
dependency: "direct main"
description:
name: intl
url: "https://pub.dartlang.org"
source: hosted
version: "0.17.0"
io:
dependency: transitive
description:
name: io
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
js:
dependency: transitive
description:
name: js
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.4"
json_annotation:
dependency: "direct main"
description:
name: json_annotation
url: "https://pub.dartlang.org"
source: hosted
version: "4.5.0"
json_serializable:
dependency: "direct dev"
description:
name: json_serializable
url: "https://pub.dartlang.org"
source: hosted
version: "6.2.0"
lints:
dependency: transitive
description:
name: lints
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
logging:
dependency: transitive
description:
name: logging
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.11"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.4"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
mime:
dependency: transitive
description:
name: mime
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
nested:
dependency: transitive
description:
name: nested
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
package_config:
dependency: transitive
description:
name: package_config
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
path:
dependency: "direct main"
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.1"
path_provider:
dependency: "direct main"
description:
name: path_provider
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.9"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.13"
path_provider_ios:
dependency: transitive
description:
name: path_provider_ios
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.8"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.5"
path_provider_macos:
dependency: transitive
description:
name: path_provider_macos
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
platform:
dependency: transitive
description:
name: platform
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.0"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
pool:
dependency: transitive
description:
name: pool
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.0"
process:
dependency: transitive
description:
name: process
url: "https://pub.dartlang.org"
source: hosted
version: "4.2.4"
provider:
dependency: "direct main"
description:
name: provider
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.2"
pub_semver:
dependency: transitive
description:
name: pub_semver
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
pubspec_parse:
dependency: transitive
description:
name: pubspec_parse
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
shared_preferences:
dependency: "direct main"
description:
name: shared_preferences
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.13"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.11"
shared_preferences_ios:
dependency: transitive
description:
name: shared_preferences_ios
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
shared_preferences_macos:
dependency: transitive
description:
name: shared_preferences_macos
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
shelf:
dependency: transitive
description:
name: shelf
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
shelf_web_socket:
dependency: transitive
description:
name: shelf_web_socket
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
source_gen:
dependency: transitive
description:
name: source_gen
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.2"
source_helper:
dependency: transitive
description:
name: source_helper
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.2"
source_span:
dependency: transitive
description:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.2"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
stream_transform:
dependency: transitive
description:
name: stream_transform
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.9"
timing:
dependency: transitive
description:
name: timing
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
uuid:
dependency: "direct main"
description:
name: uuid
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.6"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
watcher:
dependency: transitive
description:
name: watcher
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.0"
win32:
dependency: transitive
description:
name: win32
url: "https://pub.dartlang.org"
source: hosted
version: "2.5.2"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0+1"
yaml:
dependency: transitive
description:
name: yaml
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.0"
sdks:
dart: ">=2.17.0-266.1.beta <3.0.0"
flutter: ">=2.8.1"

82
pubspec.yaml Normal file
View file

@ -0,0 +1,82 @@
name: logic_circuits_simulator
description: License project
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.0+1
environment:
sdk: ">=2.17.0-266.1.beta <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
path_provider: ^2.0.9
shared_preferences: ^2.0.13
provider: ^6.0.2
path: ^1.8.1
json_annotation: ^4.5.0
freezed: ^2.0.3
freezed_annotation: ^2.0.3
intl: ^0.17.0
flutter_hooks: ^0.18.3
uuid: ^3.0.6
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
json_serializable: ^6.2.0
build_runner: ^2.1.10
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter packages.
flutter:
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/assets-and-images/#from-packages
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages

30
test/widget_test.dart Normal file
View file

@ -0,0 +1,30 @@
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility in the flutter_test package. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:logic_circuits_simulator/main.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(const MyApp());
// Verify that our counter starts at 0.
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
// Tap the '+' icon and trigger a frame.
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
// Verify that our counter has incremented.
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
});
}

BIN
web/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 917 B

BIN
web/icons/Icon-192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
web/icons/Icon-512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

58
web/index.html Normal file
View file

@ -0,0 +1,58 @@
<!DOCTYPE html>
<html>
<head>
<!--
If you are serving your web app in a path other than the root, change the
href value below to reflect the base path you are serving from.
The path provided below has to start and end with a slash "/" in order for
it to work correctly.
For more details:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
This is a placeholder for base href that will be replaced by the value of
the `--base-href` argument provided to `flutter build`.
-->
<base href="$FLUTTER_BASE_HREF">
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="License project">
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="logic_circuits_simulator">
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png"/>
<title>logic_circuits_simulator</title>
<link rel="manifest" href="manifest.json">
<script>
// The value below is injected by flutter build, do not touch.
var serviceWorkerVersion = null;
</script>
<!-- This script adds the flutter initialization JS code -->
<script src="flutter.js" defer></script>
</head>
<body>
<script>
window.addEventListener('load', function(ev) {
// Download main.dart.js
_flutter.loader.loadEntrypoint({
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
}
}).then(function(engineInitializer) {
return engineInitializer.initializeEngine();
}).then(function(appRunner) {
return appRunner.runApp();
});
});
</script>
</body>
</html>

35
web/manifest.json Normal file
View file

@ -0,0 +1,35 @@
{
"name": "logic_circuits_simulator",
"short_name": "logic_circuits_simulator",
"start_url": ".",
"display": "standalone",
"background_color": "#0175C2",
"theme_color": "#0175C2",
"description": "License project",
"orientation": "portrait-primary",
"prefer_related_applications": false,
"icons": [
{
"src": "icons/Icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icons/Icon-512.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "icons/Icon-maskable-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "icons/Icon-maskable-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
]
}

Some files were not shown because too many files have changed in this diff Show more