If I create a label in interface builder and set a string through code that does not fit its current size, the label will grow vertically to fit its size, great!.
Besides the x & y constraint, Xcode creates a NSContentSizeLayoutConstraint that contains hugging and compression resistance.
Here is a log output of the constraint
<NSContentSizeLayoutConstraint:0x6080000a11a0 V:[NSTextField:0x600000180c30(17)] Hug:750 CompressionResistance:750>
The question is, how to do this programmatically? I have not found a way yet. There is no way to create a NSContentSizeLayoutConstraint and setting the contentCompressionResistance of the NSTextField does not seem to have any effect.
Here is my code:
self.label = [[NSTextField alloc]initWithFrame:NSMakeRect(0, 0, 100, 20)];
[self.label setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.label setBordered:YES];
[[self.label cell] setLineBreakMode:NSLineBreakByWordWrapping];
[self.window.contentView addSubview:self.label];
self.label.stringValue = #"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
NSDictionary *dict = #{#"label" : self.label};
[self.label.superview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[label]"options:0 metrics:nil views:dict]];
[self.label.superview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-[label]" options:0 metrics:nil views:dict]];
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self.label attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:0 constant:40];
constraint.priority = 1;
[self.label addConstraint:constraint];
constraint = [NSLayoutConstraint constraintWithItem:self.label attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:0 constant:18];
constraint.priority = 1;
[self.label addConstraint:constraint];
[self.label setContentCompressionResistancePriority:1000 forOrientation:NSLayoutConstraintOrientationHorizontal];
[self.label setContentCompressionResistancePriority:1000 forOrientation:NSLayoutConstraintOrientationVertical];
Set the text field's preferredMaxLayoutWidth. I think you then don't want or need the explicit width constraint.
In my testing, I find that this works:
self.label = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 18)];
self.label.translatesAutoresizingMaskIntoConstraints = NO;
[self.label.cell setLineBreakMode:NSLineBreakByWordWrapping];
self.label.stringValue = #"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
self.label.preferredMaxLayoutWidth = 100;
self.label.editable = NO;
[self.window.contentView addSubview:self.label];
NSDictionary* views = #{ #"label" : self.label };
[self.label.superview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[label]" options:0 metrics:nil views:views]];
[self.label.superview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-[label]" options:0 metrics:nil views:views]];
Basically, the main difference from yours is that I set editable to NO. I also leave out the width and height constraints and setting the compression resistance.
I think a better way to do this, is to override NSTextField, and update the intrinsicContentSize.
public class DynamicTextField: NSTextField {
public override var intrinsicContentSize: NSSize {
if cell!.wraps {
let fictionalBounds = NSRect(x: bounds.minX, y: bounds.minY, width: bounds.width, height: CGFloat.greatestFiniteMagnitude)
return cell!.cellSize(forBounds: fictionalBounds)
} else {
return super.intrinsicContentSize
}
}
public override func textDidChange(_ notification: Notification) {
super.textDidChange(notification)
if cell!.wraps {
validateEditing()
invalidateIntrinsicContentSize()
}
}
}
Afterwards the constraints works as expected. Note that it only works when you set the Layout to Wraps in Interface Builder or code.
Related
My problem is, that coreui in laravel does render the components, but none of them are interactive. For example when I use Tabs (CTabs), then it gets displayed correctly, but I cannot switch the tabs.
This is how I load coreui and the components:
import CoreuiVue from '#coreui/vue';
Vue.use(CoreuiVue);
// Registering a single component
import { CSwitch, CButton, CTabs, CTab, CCarousel, CCarouselItem } from '#coreui/vue';
Vue.component('CTabs', CTabs)
Vue.component('CTab', CTab)
Vue.component('CCarousel', CCarousel)
Vue.component('CCarouselItem', CCarouselItem)
// globally
Vue.directive('c-emit-root-event', CEmitRootEvent)
export default {
components: {
CTabs, CTab, CCarousel, CCarouselItem
},
directives: {
'c-tooltip': CTooltip
},
}
Vue.component(
'example-component',
require('./components/ExampleComponent.vue').default
);
const app = new Vue({
el: '#my-app',
data(){
}
});
Then the ExampleComponent.vue
<template>
<div>
<CTabs variant="pills" :active-tab="0">
<CTab title="Home">
1. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore
et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui
officia deserunt mollit anim id est laborum.
</CTab>
<CTab title="Profile">
2. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore
et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui
officia deserunt mollit anim id est laborum.
</CTab>
<CTab title="Disabled" >
Text will not be shown.
</CTab>
</CTabs>
<CCarousel
arrows
indicators
animate
height="450px"
>
<CCarouselItem
captionHeader="First Slide"
image="https://picsum.photos/1024/480/?image=52"
captionText="Nulla vitae elit libero, a pharetra augue mollis interdum."
/>
<CCarouselItem
captionHeader="Blank page"
:image="{ placeholderColor: 'grey' }"
captionText="Nulla vitae elit libero, a pharetra augue mollis interdum."
/>
<CCarouselItem
image="https://picsum.photos/1024/480/?image=54"
/>
</CCarousel>
</div>
</template>
<script>
module.exports = {
data: function () {
return {
message : 'Hello Vue!!'
}
},
name: 'example-component'
}
</script>
and the view file
<div id="my-app">
<example-component></example-component>
</div>
Any ideas?
I simply had to wrap the Vue Object into DOMContentLoaded to make sure that the DOM is ready before attaching vue.js.
document.addEventListener("DOMContentLoaded", function(event) {
const app = new Vue({
el: '#my-app',
data(){
}
});
})
I created a swift file using a class called Course . Everything works in my code except when I try to input the URL. I get an error Message.
Here's is my sample code
URL(String:"https://www.youtube.com/watch?v=QBULK-w-i90")!
I keep getting error
Argument labels '(String)' do not match any available overloads
I'm not sure what that means and how can I fix this problem .
here is the code written out I follow video but keep getting errors.
import UIKit
class CourseStore
{
class func downloadNewCourses()-> [Course]
{
var courses = [Course]()
let chefCourse = Course(buttonImage: #imageLiteral(resourceName: "cover_chef"),
title: "Become a Pro Chef",
instructor: "Gordon Ramsay",
featuredImage: #imageLiteral(resourceName: "chef"),
introductionVideoUrl: URL(String:"https://www.youtube.com/watch?v=QBULK-w-i90")!,
introductionVideoUrl: ,
description: "Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda."
)
return courses
}
}
Argument labels '(String)' do not match any available overloads
Means that URL doesn't have constructor which has those parameters. In your case you named parameter String but it should be lowercased string.
Instead use
URL(string: "https://www.youtube.com/watch?v=QBULK-w-i90")!
I have the following file format:
Text1
+ continuation of Text1
+ more continuation of Text1
Text2
+ continuation of Text2
+ more continuation of Text2
+ even more continuation of Text2
Continuations are marked by \n+. (Newline, plus character, space as a three character string.) Continuations can be any number of lines, including 0.
I want the following output (each is a line printed with .forEach):
Text1 continuation of Text1 more continuation of Text1
Text2 continuation of Text2 more continuation of Text2 even more continuation of Text2
I would like to use only Java streams to do the conversion, preferably with Collect. Is there a way to do this elegantly?
EDIT:
Another, more realistic example:
Lorem ipsum dolor sit amet, consectetur
+ adipiscing elit, sed do eiusmod tempor incididunt
+ ut labore et dolore magna aliqua. Ut enim ad minim veniam,
+ quis nostrud exercitation ullamco laboris nisi ut aliquip ex
+ ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit
+ esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
+ occaecat cupidatat non proident, sunt in culpa qui officia
+ deserunt mollit anim id est laborum.
Expected result is two lines:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
In Java 9, you could use
static final Pattern LINE_WITH_CONTINUATION = Pattern.compile("(\\V|\\R\\+)+");
…
try(Scanner s = new Scanner(file)) {
s.findAll(LINE_WITH_CONTINUATION)
.map(m -> m.group().replaceAll("\\R\\+", ""))
.forEach(System.out::println);
}
Since Java 8 lacks the Scanner.findAll(Pattern) method, you may add a custom implementation of the operation as a work-around
public static Stream<MatchResult> findAll(Scanner s, Pattern pattern) {
return StreamSupport.stream(new Spliterators.AbstractSpliterator<MatchResult>(
1000, Spliterator.ORDERED|Spliterator.NONNULL) {
public boolean tryAdvance(Consumer<? super MatchResult> action) {
if(s.findWithinHorizon(pattern, 0)!=null) {
action.accept(s.match());
return true;
}
else return false;
}
}, false);
}
which can be used like
try(Scanner s = new Scanner(file)) {
findAll(s, LINE_WITH_CONTINUATION)
.map(m -> m.group().replaceAll("\\R\\+", ""))
.forEach(System.out::println);
}
which will make the future migration easy.
Assuming that you run this sequentially only and really want to use streams:
List<String> result = Files.lines(Paths.get("YourPath"))
.collect(() -> new ArrayList<>(), (list, line) -> {
int listSize = list.size();
if (line.startsWith("+ ")) {
list.set(listSize - 1, list.get(listSize - 1) + line.substring(2));
} else {
list.add(line);
}
}, (left, right) -> {
throw new RuntimeException("Not for parallel processing");
});
Trying to teach myself how to do custom drawing in OS X. I am trying to nest a NSTextView within a NSView.
I can't seem to figure out the step I am missing to get the NSTextView to behave as if it wasn't embedded in another custom view (I.e., text should begin redering from top-left in the frame provided to the NSTextView, left-to-right and top-to-bottom).
import Cocoa
import AppKit
import XCPlayground
class MyView : NSView {
let lipsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
override init(frame: NSRect) {
super.init(frame:frame)
self.wantsLayer = true
}
required init(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
let grey = NSColor.grayColor()
self.layer?.backgroundColor = grey.CGColor
let boundaryRect = NSInsetRect(dirtyRect, 10, 10)
let textRect = NSInsetRect(boundaryRect, 10, 10)
let path = NSBezierPath(roundedRect: boundaryRect, xRadius: 5, yRadius: 5)
path.stroke()
let text = NSTextView(frame: textRect)
text.backgroundColor = grey
text.insertText(lipsum)
text.drawRect(textRect)
}
}
var frame = NSRect(x: 0, y: 0, width: 400, height: 400)
let myView = MyView(frame: frame)
let textView = NSTextView(frame:frame)
textView.insertText(myView.lipsum)
XCPShowView("my view", myView)
XCPShowView("text view", textView)
You haven't actually embedded the text view inside the parent view. You can do that with addSubview().
let text = NSTextView(frame: textRect)
text.backgroundColor = grey
text.insertText(lipsum)
self.addSubview(text) // <---------
}
I'm trying to implement text search with linq. I have a Messages table which is populated with emails data. I want to be able to search in Messages body. However emails bodies are very long and I will like to display only small part of the searched text for example if I search for:
aute
in the following text:
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
the result should be:
...aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur....
Thanks
Something like this should do the job:
var query = from str in messages
let index = str.IndexOf(search)
where index > -1
select str.Substring(Math.Max(0, index - radius), radius + Math.Min(radius, str.Length - index));
Where messages is your email string list, and radius is an int describing how many characters you want to take before and after the string you are looking for. Note that this code will only return the first match in every email, ignoring the other ones.
Everything would be easier if you could use an helper function to calculate the proper substring tho.
Here you can find an extension method that implements a safe version of string.substring, making hte above linq code look something like:
var query = from str in lst
let index = str.IndexOf(search)
where index > -1
select str.SafeSubstring(index - radius, 2*radius);
that in my opinion is much simnpler to read
EDIT
Extending string with the two following methods :
public static List<int> IndexOfAll(this String str, string search)
{
List<int> lst = new List<int>();
foreach (Match match in Regex.Matches(str,search))
{
lst.Add(match.Index);
}
return lst;
}
public static string SafeSubstring(this String str, int start, int n)
{
return str.Substring(Math.Max(start, 0), Math.Min(n, str.Length - start));
}
you can get all the results in a nice form, using
var query = from str in lst
let index = str.IndexOfAll(search)
where index.Count>0
select index.Select(x => str.SafeSubstring(x-radius, 2*radius));
with query as an IEnumerable