Commit abcdd3b4 authored by Wei Han's avatar Wei Han

UI update for plan page

parent 3806f808
......@@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */
2F8D09092E9605E200C764FF /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F8D09082E9605E200C764FF /* CoreGraphics.framework */; };
2F99420D2EA9C5F000622199 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F99420C2EA9C5F000622199 /* QuartzCore.framework */; };
2FAEF09A2E8B7BC80086EDA3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FAEF0992E8B7BC80086EDA3 /* UIKit.framework */; };
2FAEF09C2E8B7BD40086EDA3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FAEF09B2E8B7BD40086EDA3 /* Foundation.framework */; };
/* End PBXBuildFile section */
......@@ -15,6 +16,7 @@
/* Begin PBXFileReference section */
2F8D09082E9605E200C764FF /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.0.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; };
2F9647652E86307D002CC7CB /* QmsPluginFramework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = QmsPluginFramework.framework; sourceTree = BUILT_PRODUCTS_DIR; };
2F99420C2EA9C5F000622199 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.0.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; };
2FAEF0992E8B7BC80086EDA3 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.0.sdk/System/iOSSupport/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
2FAEF09B2E8B7BD40086EDA3 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
/* End PBXFileReference section */
......@@ -46,6 +48,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
2F99420D2EA9C5F000622199 /* QuartzCore.framework in Frameworks */,
2F8D09092E9605E200C764FF /* CoreGraphics.framework in Frameworks */,
2FAEF09C2E8B7BD40086EDA3 /* Foundation.framework in Frameworks */,
2FAEF09A2E8B7BC80086EDA3 /* UIKit.framework in Frameworks */,
......@@ -75,6 +78,7 @@
2FAEF0982E8B7BC80086EDA3 /* Frameworks */ = {
isa = PBXGroup;
children = (
2F99420C2EA9C5F000622199 /* QuartzCore.framework */,
2F8D09082E9605E200C764FF /* CoreGraphics.framework */,
2FAEF09B2E8B7BD40086EDA3 /* Foundation.framework */,
2FAEF0992E8B7BC80086EDA3 /* UIKit.framework */,
......
......@@ -15,6 +15,8 @@
@property (nonatomic, strong) NSDictionary *unitPlanData;
@property (nonatomic, strong) NSArray *locations;
@property (nonatomic, strong) NSString *planImageURL;
@property (nonatomic, assign) CGFloat planWidth;
@property (nonatomic, assign) CGFloat planHeight;
@end
......@@ -36,6 +38,12 @@
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[self.view bringSubviewToFront:self.headerView];
static BOOL hasRenderedLocations = NO;
if (!hasRenderedLocations && self.planImageView.image && self.locations.count > 0) {
hasRenderedLocations = YES;
[self renderAllLocations:self.locations];
}
}
- (void)fetchInitialData {
......@@ -54,7 +62,7 @@
[jsonData writeToFile:filePath atomically:YES];
NSLog(@"📁 UnitPlan saved to %@", filePath);
// 🔍 Parse the JSON
// 🔍 Parse JSON
NSDictionary *appData = data[@"AppData"];
if (![appData[@"status"] isEqualToString:@"success"]) {
NSLog(@"⚠️ Server returned non-success status: %@", appData[@"message"]);
......@@ -71,20 +79,36 @@
self.unitPlanData = mainData.firstObject;
self.locations = self.unitPlanData[@"location"];
// Extract first issue’s plan image URL
if (self.locations.count == 0) {
NSLog(@"⚠️ No locations found in plan");
return;
}
// ✅ Extract plan dimensions and image URL
NSDictionary *firstLocation = self.locations.firstObject;
NSDictionary *firstIssue = [firstLocation[@"issue"] firstObject];
NSArray *issues = firstLocation[@"issue"];
if (issues.count == 0) {
NSLog(@"⚠️ No issues found under first location");
return;
}
NSDictionary *firstIssue = issues.firstObject;
NSString *widthStr = [NSString stringWithFormat:@"%@", firstIssue[@"plan_width"]];
NSString *heightStr = [NSString stringWithFormat:@"%@", firstIssue[@"plan_height"]];
self.planWidth = [widthStr floatValue];
self.planHeight = [heightStr floatValue];
self.planImageURL = firstIssue[@"plan_image"];
NSLog(@"📐 Plan dimensions: width = %f, height = %f", self.planWidth, self.planHeight);
NSLog(@"🗺 Found %lu locations", (unsigned long)self.locations.count);
NSLog(@"🖼 Plan image URL: %@", self.planImageURL);
// Now update the UI on main thread
// Update UI on main thread
dispatch_async(dispatch_get_main_queue(), ^{
[self displayPlanImage];
[self debugPrintAllIssues];
});
}];
[self debugPrintAllIssues];
}
- (void)displayPlanImage {
......@@ -116,6 +140,9 @@
dispatch_async(dispatch_get_main_queue(), ^{
self.planImageView.image = image;
[self.scrollView setZoomScale:1.0 animated:NO];
[self.view setNeedsLayout];
[self.view layoutIfNeeded];
[self renderAllLocations:self.locations];
NSLog(@"✅ Plan image displayed successfully");
});
}];
......@@ -169,7 +196,7 @@
self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.titleLabel.text = self.projectName ?: @"Plan Viewer";
self.titleLabel.textColor = UIColor.whiteColor;
self.titleLabel.font = [UIFont boldSystemFontOfSize:18];
self.titleLabel.font = [UIFont boldSystemFontOfSize:20];
self.titleLabel.textAlignment = NSTextAlignmentCenter;
[self.headerView addSubview:self.titleLabel];
......@@ -178,13 +205,13 @@
subtitleLabel.translatesAutoresizingMaskIntoConstraints = NO;
subtitleLabel.text = self.projectCode ?: @"";
subtitleLabel.textColor = [UIColor colorWithWhite:1.0 alpha:0.8];
subtitleLabel.font = [UIFont systemFontOfSize:13 weight:UIFontWeightRegular];
subtitleLabel.font = [UIFont systemFontOfSize:15 weight:UIFontWeightRegular];
subtitleLabel.textAlignment = NSTextAlignmentCenter;
[self.headerView addSubview:subtitleLabel];
// ✅ Constraints
UILayoutGuide *safe = self.view.safeAreaLayoutGuide;
CGFloat headerHeight = 80.0; // ⬆️ Taller header now
CGFloat headerHeight = 110.0; // header height
[NSLayoutConstraint activateConstraints:@[
// Status bar background
......@@ -211,17 +238,18 @@
[self.helpButton.widthAnchor constraintEqualToConstant:44],
[self.helpButton.heightAnchor constraintEqualToConstant:44],
// Title label (below buttons)
// Title label (below buttons, left-aligned)
[self.titleLabel.topAnchor constraintEqualToAnchor:self.backButton.bottomAnchor constant:4],
[self.titleLabel.centerXAnchor constraintEqualToAnchor:self.headerView.centerXAnchor],
[self.titleLabel.leadingAnchor constraintEqualToAnchor:self.headerView.leadingAnchor constant:16],
[self.titleLabel.trailingAnchor constraintLessThanOrEqualToAnchor:self.helpButton.leadingAnchor constant:-8],
// Subtitle (below title)
// Subtitle (below title, left-aligned)
[subtitleLabel.topAnchor constraintEqualToAnchor:self.titleLabel.bottomAnchor constant:2],
[subtitleLabel.centerXAnchor constraintEqualToAnchor:self.headerView.centerXAnchor],
[subtitleLabel.leadingAnchor constraintEqualToAnchor:self.titleLabel.leadingAnchor],
[subtitleLabel.trailingAnchor constraintLessThanOrEqualToAnchor:self.helpButton.leadingAnchor constant:-8],
]];
}
- (void)loadPlanImageFromURL:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
if (!url) return;
......@@ -273,6 +301,19 @@
NSDictionary *unitPlan = mainData.firstObject;
self.unitPlanData = unitPlan;
// ✅ Extract and store plan dimensions (ensure they’re numeric)
NSString *widthStr = [NSString stringWithFormat:@"%@", unitPlan[@"plan_width"]];
NSString *heightStr = [NSString stringWithFormat:@"%@", unitPlan[@"plan_height"]];
self.planWidth = [widthStr floatValue];
self.planHeight = [heightStr floatValue];
NSLog(@"📏 planWidth = %f, planHeight = %f", self.planWidth, self.planHeight);
// 🧱 Safety check
if (self.planWidth <= 0 || self.planHeight <= 0) {
NSLog(@"⚠️ Invalid plan dimensions — overlays may not render correctly.");
}
// Save JSON for debugging
NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
NSString *filePath = [docsPath stringByAppendingPathComponent:@"unitPlanParsed.json"];
......@@ -288,7 +329,7 @@
NSLog(@"⚠️ No plan_image found in response");
}
// ✅ (Optional) Update title or debug log
// ✅ Update title
NSString *unitName = unitPlan[@"unit_name"] ?: @"No name";
dispatch_async(dispatch_get_main_queue(), ^{
self.titleLabel.text = unitName;
......@@ -310,6 +351,11 @@
self.scrollView.delegate = (id<UIScrollViewDelegate>)self;
self.scrollView.minimumZoomScale = 1.0;
self.scrollView.maximumZoomScale = 5.0;
self.scrollView.bouncesZoom = YES;
self.scrollView.alwaysBounceVertical = YES;
self.scrollView.alwaysBounceHorizontal = YES;
self.scrollView.showsVerticalScrollIndicator = NO;
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.scrollView];
......@@ -338,6 +384,91 @@
]];
}
- (void)renderLocation:(NSDictionary *)locationData onImageView:(UIImageView *)planImageView {
if (!planImageView.image) return;
CGRect imageRect = [self imageRectInImageView:planImageView];
CGFloat displayedWidth = imageRect.size.width;
CGFloat displayedHeight = imageRect.size.height;
NSArray *issues = locationData[@"issue"];
NSLog(@"Total issues: %lu", (unsigned long)issues.count);
NSLog(@"planWidth: %f, planHeight: %f", self.planWidth, self.planHeight);
CGFloat scaleX = displayedWidth / self.planWidth;
CGFloat scaleY = displayedHeight / self.planHeight;
NSArray *points = locationData[@"points"];
if (!points || points.count == 0) {
NSLog(@"⚠️ No points found for location %@", locationData[@"id"]);
return;
}
UIBezierPath *path = [UIBezierPath bezierPath];
for (int i = 0; i < points.count; i++) {
NSDictionary *point = points[i];
CGFloat x = imageRect.origin.x + [point[@"x"] doubleValue] * scaleX;
CGFloat y = imageRect.origin.y + [point[@"y"] doubleValue] * scaleY;
if (i == 0) [path moveToPoint:CGPointMake(x, y)];
else [path addLineToPoint:CGPointMake(x, y)];
// 🔵 Visual dot marker
// UIView *dot = [[UIView alloc] initWithFrame:CGRectMake(x - 2, y - 2, 4, 4)];
// dot.backgroundColor = [UIColor blueColor];
// dot.layer.cornerRadius = 2;
// [planImageView addSubview:dot];
NSLog(@"📍 Point %d -> x=%f, y=%f", i, x, y);
if (x < imageRect.origin.x || y < imageRect.origin.y ||
x > imageRect.origin.x + imageRect.size.width ||
y > imageRect.origin.y + imageRect.size.height) {
NSLog(@"⚠️ Point %d is out of bounds!", i);
}
}
[path closePath];
CAShapeLayer *polygonLayer = [CAShapeLayer layer];
polygonLayer.path = path.CGPath;
polygonLayer.fillColor = UIColor.clearColor.CGColor;
polygonLayer.strokeColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.3].CGColor;
polygonLayer.lineWidth = 2.0;
[planImageView.layer addSublayer:polygonLayer];
}
- (CGRect)imageRectInImageView:(UIImageView *)imageView {
CGSize imageSize = imageView.image.size;
CGSize viewSize = imageView.bounds.size;
CGFloat scale = MIN(viewSize.width / imageSize.width, viewSize.height / imageSize.height);
CGFloat width = imageSize.width * scale;
CGFloat height = imageSize.height * scale;
CGFloat x = (viewSize.width - width) / 2.0;
CGFloat y = (viewSize.height - height) / 2.0;
return CGRectMake(x, y, width, height);
}
- (void)renderAllLocations:(NSArray *)locations {
for (NSDictionary *locationData in locations) {
[self renderLocation:locationData onImageView:self.planImageView];
}
}
- (UIColor *)colorFromHex:(NSString *)hexString {
unsigned int rgbValue = 0;
NSScanner *scanner = [NSScanner scannerWithString:[hexString stringByReplacingOccurrencesOfString:@"#" withString:@""]];
[scanner scanHexInt:&rgbValue];
return [UIColor colorWithRed:((rgbValue >> 16) & 0xFF) / 255.0
green:((rgbValue >> 8) & 0xFF) / 255.0
blue:(rgbValue & 0xFF) / 255.0
alpha:1.0];
}
- (void)handleNextScreen {
[self showAddIssuePopup];
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment