Git Product home page Git Product logo

twui's Introduction

TwUI

TwUI is a hardware accelerated UI framework for Mac, inspired by UIKit. It enables:

  • GPU accelerated rendering backed by CoreAnimation
  • Simple model/view/controller development familiar to iOS developers

It differs from UIKit in a few ways:

  • Simplified table view cells
  • Block-based layout and drawRect
  • A consistent coordinate system (bottom left origin)
  • Sub-pixel text rendering

Setup

To use the current development version, include all the files in your project and import TUIKit.h. Set your target to link to the ApplicationServices and QuartzCore frameworks.

Usage

Your TUIView-based view hierarchy is hosted inside an TUINSView, which is the bridge between AppKit and TwUI. You may set a TUINSView as the content view of your window, if you'd like to build your whole UI with TwUI. Or you may opt to have a few smaller TUINSViews, using TwUI just where it makes sense and continue to use AppKit everywhere else.

You can also add NSViews to a TwUI hierarchy using TUIViewNSViewContainer, which bridges back into AppKit from TwUI.

Example Project

An included example project shows off the basic construction of a pure TwUI-based app. A TUINSView is added as the content view of the window, and some TUIView-based views are hosted in that. Within the table view cells, some NSTextFields are also added using TUIViewNSViewContainer. It includes a table view and a tab bar (which is a good example of how you might build your own custom controls).

Status

TwUI is currently shipping in Twitter for Mac and GitHub for Mac, in use 24/7 by many, many users, and has proven itself very stable.

This project follows the SemVer standard. The API may change in backwards-incompatible ways between major releases.

The goal of TwUI is to build a high-quality UI framework designed specifically for the Mac. Much inspiration comes from UIKit, but diverging to try new things (i.e. block-based layout and drawRect), and optimizing for Mac-specific interactions is encouraged.

Contributing

We will happily accept pull requests that meet one of the following criteria:

  1. It fixes some functionality that is already in TwUI. This might be a bug, or something not working as expected.
  2. It's something so basic or important that TwUI really should have it.
  3. It has to integrate with TwUI internals, and so can't easily be done outside of the framework. This one is the most ambiguous, because interesting things may match this criterion, but still be way out of scope. In some cases, a fork might be more appropriate. Use your best judgment.

All contributions should match our coding conventions.

Community

TwUI has a mailing list, subscribe by sending an email to [email protected].

Copyright and License

Copyright 2011 Twitter, Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with the License. You may obtain a copy of the License in the LICENSE file, or at:

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

twui's People

Contributors

aroben avatar avaidyam avatar bigboybad avatar boidanny avatar brutella avatar caniszczyk avatar codafi avatar dannygreg avatar dmitshur avatar fabiopelosin avatar jagreenwood avatar jboley avatar joshaber avatar jspahrsummers avatar jwilling avatar kylebrowning avatar lorenbrichter avatar luosheng avatar mdiep avatar ncuesta avatar patr1ck avatar peterarnott avatar robrix avatar sandofsky avatar shadoflamex avatar thekarladam avatar zachwaugh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

twui's Issues

NSImage and @2x

It seems that with the recent killing of TUIImage that we're back to square one in regards to @2x support again. If you have a HiDPi display, you can easily see that the example project does not draw in high resolution, even though @2x assets are provided.

TUIPopover

I've modified the TUIPopover to near-perfectly (like, nearly indistinguishably) mimic the NSPopover, but this also removes the ability to set a custom style and custom TUIPopoverBackgroundView. Should I consider a pull request for it? The main reason I did this was for the shadow on the popover, along with the transparency. For some reason, both of them don't like each other.

NSTextField hosted in a TUITableViewCell - Text flips during certain animations

This can be seen in the example project:

Steps to reproduce:

  • Run the example
  • Enter some text in one of the NSTextFields in the table view
  • Drag the row below it upward
  • The text entered in the NSTextField flips upside down until the re-order animation completes

It can be difficult to see since the problem row slides behind the row being dragged. It's easier to see if the test you enter is something like "AAAAAAAA", pretty obvious when that flips upside down.

Removal of certain "tui" prefixed methods.

A few tui_ prefixed methods don't have to be prefixed, such as tui_performWithDisabledActions, tui_CGImage, tui_fontWithName, and a few more NSImage methods. These aren't necessarily private methods, they don't conflict with existing methods, and would be used fairly often in TwUI. Is there a reason they need to be prefixed?

TUIDrawer....?

Yes, I know that NSDrawers have long since been considered the bane of AppKit's existence (along with NSCell), but, as with TUIPopover, a TwUI-based customizable NSPopover, would it be possible to create something like a TUIDrawer? It would be fairly similar, aside from a few design pattern differences.

Refactoring and renaming.

I suggest we add categories to NSColor and NSImage and the like to match the long-lost TUIImage and TUIColor, which had simpler method names and more. I also suggest we rename a few classes such as TUINSView and NSTUIView to something that makes more sense and keeps a TUI* prefix.

TUIViewNSViewContainer doesn't work as expected

Here's the scenario: I have a TUIView called ExampleView acting as the rootView of a TUINSView and I want to add an NSView to it. So I copy the following code from TwUI's ExampleProject and paste it to ExampleView's initWithFrame: method.

NSTextField *textField = [[NSTextField alloc] initWithFrame:NSMakeRect(20, 180, 91, 22)];
[textField.cell setUsesSingleLineMode:YES];
[textField.cell setScrollable:YES];

self.textFieldContainer = [[TUIViewNSViewContainer alloc] initWithNSView:textField];
self.textFieldContainer.backgroundColor = [NSColor blueColor];
[self addSubview:self.textFieldContainer];

It was supposed to show a text field on the screen. However it just showed a blue rectangle instead (the TUIViewNSViewContainer).

So I looked into the source of TUIViewNSViewContainer. It tried to add the NSView to its ancestorTUINSView's appKitHostView. However, at that time the TUIViewNSViewContainer's ancestorTUINSView property is still nil becasuse here's how we initialize the ExampleView in the ExampleAppDelegate:

TUINSView *tuiTableViewContainer = [[TUINSView alloc] initWithFrame:b];
[tableViewWindow setContentView:tuiTableViewContainer];

ExampleView *tableExample = [[ExampleView alloc] initWithFrame:b];
tuiTableViewContainer.rootView = tableExample;

The ExampleView's nsView property is set in the last statement when TUINSView's setRootView method is called. So adding a NSView to TUIView in the initWithFrame: method before it won't work.

The ExampleProject works because text fields are added to the table cells, which are initialized after TUIViewNSViewContainer's nsView is set.

TUILayoutConstraint Additions

At the moment, my implementation of TUILayoutConstraint only supports equality constraints (==). It would be nice if they supported inequalities (>=, <=, >, <), but alas, I have no idea how to go about this. Would anyone have an ideas on how to implement this?

There's also a few things I'd like to fix:

  • A weird superview layout bug (requiring the superview to have a layout name).
  • Removal of layout names: I'm thinking of using -[NSProcessInfo globallyUniqueString] instead.
  • ASCII-art based layout construction - this one's a LOT harder.
  • AppKit bridging for layouts. I have no idea how the current bridging architecture works though.

VFL (Autolayout language) is documented here:
http://developer.apple.com/library/mac/#documentation/UserExperience/Conceptual/AutolayoutPG/Articles/formatLanguage.html#//apple_ref/doc/uid/TP40010853-CH3

TUIPopover transparent background

I can't figure out for the life of me how to have a transparent background (like MAAttachedWindow) using a TUIPopover background view class. It just doesn't work. I ended up rewriting the class to make that work, but it should be possible without a rewrite. What am I doing wrong!??!

TUITableView reports it's contentOffset in the 10's of thousands

TUITableView appears to be incorrectly calculating it's -contentOffset by multiplying the number of cells it has by their heights, then adding the size of its -pullDownView and negating the whole deal. This appears to be a side effect of the Mac's coordinate system, but I have no idea where the negatives are coming from.

Sample logs from

- (void)scrollViewDidScroll:(TUIScrollView *)scrollView{
    NSLog(@"%@", NSStringFromPoint(NSPointFromCGPoint(scrollView.contentOffset)));    
}

{0, -17597}
{0, -17596}
{0, -17594}
{0, -17593}
{0, -17593}
{0, -17592}
{0, -17591}
{0, -17590}

Default initializers do not call standard initializers

Scattered throughout the framework are controls which have the propensity to not initialize themselves completely if, say, -init is called over -initWithFrame:. Controls that exhibit this behavior often do not show themselves (such as TUIButton) in the view because they forget to initialize their subcomponents. I propose a change to the coding conventions, in that setup work that does not involve the parameter(s) requested by the default initializer be done in -init or -commonInit so that all initializers in the framework create valid, and complete versions of themselves.

Missing features in TwUI

I've listed below what I think are things TwUI should have, can have, and are not that hard to implement. I'm working on a few of these right now, but I've added this list here for the community to add/remove to/from the list, and discuss any changes that could be made. The main twitter/twui fork hasn't been updated in a while now, so I'm posting on the current active fork of TwUI.

Look and Feel:

I suggest TwUI use appearance containers which allow switchable styles. For example:

  • Standard: This appearance would mimic and blend in with Cocoa.
  • Light: This would have a brighter scheme, similar to NSPopover.
  • Dark: This would be a minimal black and white, like MBProgressHUD.

The way an appearance container would work, is it would define certain theme colors, fonts, and even drawing and layout blocks. For a control that supports an appearance container, it would have to override its own drawing block/drawRect and layoutSubviews/layout block when you set an appearance container to the object.

A simple example: TUILabel could be assigned an appearance container with a primary color black, a secondary color white, an inset for shadow, and a constraint for its position.
A complex example: a TUIProgressBar could be assigned a whole drawing block for HUD, that would be a simple rounded rectangle, or a drawing block for a cocoa-style animated progress bar.

Standard Controls:

  • At the moment we have very few controls, compared to Cocoa or UIKit.
  • Add TUISplitView.
  • Add a full-fledged implementation of a tab bar (vertical or horizontal).

Navigation Stack:

As far as I know, the reason TwUI doesn't have any navigation-related elements is because of the lack of unification of such elements on Mac; some apps use a breadcrumb bar with back and forward buttons, some use iOS-like navigation headers, and some use a custom derivative. To simplify this, TwUI could allow for a navigation stack engine, and allow the developer to implement it themselves by conforming to a protocol (like NSTextInputClient).

  • Class TUINavigationStack could hold a simple view stack, pushed and popped, with a root view.
  • Protocol TUINavigationPresenter could have methods such as -navigationStack:willPush/PopView: or -navigationStack:willTransitionFromView:toView:, to allow for transitions, view updates, and more.

The best part about this is that TwUI doesn't deal with any of the transition animations, views, or data. It just simply allows for pushing and popping a view with "styles" or "transitions". The developer can then write a custom navigation bar, for example, and connect them together. Or perhaps even more complex presentations.

Inserting TwUI hierarchy into an existing layer with background

Hey,

I have a layer-hosting NSView with its own background.

If I simply insert a CATextLayer into that layer, everything looks great.

Now I try this:

  1. Create TwUI hierarchy using TUINSView.
  2. Add a new TUIView that uses TUITextRenderer to render something.
  3. Set backgrounds of all TwUI views to clearColor.

The text rendering is very ugly. I understand that normally, layer needs to have a background in order for that subpixel AA to work, but in this case my parent layer is the background.

My first experiment (inserting simple CATextLayer with clear background) proves that it should work.

Can anybody help me please?

TUITableViewCell Gradients

Many UIKit and AppKit controls (such as the source list, or table view) have gradient drawing built in as part of their API. However, TwUI does not. I strongly urge for gradient support in TUITableViewCell as a complement to a source list component I'm working on. It's not the 1% case-- it's more like the 60% case that wants gradients. Even providing a non-API feature such as a gradient drawing block would be beneficial with little impact.

TUINSWindow

To what respect are we to flesh out TUINSWindow? I do recall @joshaber saying it would be a welcome addition, but as long as it wasn't extravagant.

Remote view rendering

Much like how iOS has the hidden UIRemoteView and UIRemoteViewController, I've been doing some research into remote rendering. Perhaps this would be a beneficial addition to TwUI for a few reasons: Mac App Store requires XPC/"separation of powers", and having remotely rendered views means it's much more safe to isolate components of your application (such as a status bar from the main application window, from an aux window of some sort), and the MFMailComposeViewController in iOS 6 already employs this well.

So far, what I've determined is the hierarchy should be as follows:

  • Control order: TUIRemoteViewController --> TUIRemoteView --> TUIRemoteLayer.
  • The TUIRemoteLayer should use a custom CARenderer to draw into an IOSurface.
  • The IOSurface should be shared through mach ports between the two processes.
  • The client TUIRemoteLayer should somehow (?) draw the IOSurface's texture on itself.
  • The client TUIRemoteView should pass all events through mach ports to the other TUIRemoteView.

This way, remote view rendering and event handling is possible. Any thoughts?

EDIT: So far, I've got an OpenGL demo working with a pretty slick API. Time to figure out how to get CALayer and CARenderer in there.

NSColor CGColor property

There's already a CGColor property on NSColor. Is there a reason we need to add a new tui_CGColor property?

dequeueReusableCellWithIdentifier return cells in reverse order

I could be wrong, but it seems reusable cell mechanism work not quite correct.
For example - we create 4 cells in table, their addresses are:
     <CustomCell: 0x101ca6740>
     <CustomCell: 0x10026ac30>
     <CustomCell: 0x101cac380>
     <CustomCell: 0x10026f2d0>

After reloadData, dequeueReusableCellWithIdentifier returned:
     <CustomCell: 0x10026f2d0>
     <CustomCell: 0x101cac380>
     <CustomCell: 0x10026ac30>
     <CustomCell: 0x101ca6740>

The title of TUIButton won't draw unless "titleLabel" is accessed

The following code is supposed to create a black button with a red title on it. However it only shows a black rectangle without any text.

TUIButton *button = [[TUIButton alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
[button setTitle:@"Test" forState:TUIControlStateNormal];
[button setTitleColor:[NSColor redColor] forState:TUIControlStateNormal];
[button setBackgroundColor:[NSColor blackColor]];
[self addSubview:button];

It's because the ivar _titleView is only initialized when property titleLabel is accessed in TUIButton.m. But in drawRect:, text values and colors are assigned to a non-initialized ivar _titleView, and [_titleView drawRect:_titleView.bounds] doesn't work as expected since _titleView is nil.

Please change _titleView to self.titleLabel in drawRect:, or at least the first occurrence of _titleView.

Code cleanup!

As the code base of TwUI has expanded massively since the first release, I do think it's time for a clean up. A lot of methods are cluttered with nested statements and need to be factored, and there are a few event-lock-loops in there (while(1) { doSomething(event); getNewEvent(); }) that need to be safety proofed. Our documentation is also VERY lacking.

For now, this is a bulletin notice, as I'll begin to work on a few of these issues, but I certainly cannot do this alone. And someone has GOT to teach me to put Xcode in tabs-only mode. That bugger's driving me bonkers.

TUITableView -reloadLayout does not update cell data

Please correct me if I'm wrong, but from the scarce documentation in the header of TUITableView it appears that the cells, along with the layout + data, are supposed to be reloaded. This appears to not be the case.

When calling -reloadLayout, it seems that -cellForRowAtIndexPath is never called, which means that the cell never has a chance to react to new data. Is this intentional?

TUIImageRenderer?

Much like TUITextRenderer which deals solely with the rendering of text onto a CALayer, why not offload the tui_ methods on NSImage to a TUIImageRenderer object which, when told to draw, draws onto a layer with the chain of effects blocks?

The ExampleTabBar tabs are drawn by following a chain of image processing methods on NSImage.

The benefits include exporting these methods into another class, leaving NSImage with less burden in case of OS API updates (No more tui_ prefixing!), and more.

NOTE: I don't mean we need to add more features; just put less and less responsibility on AppKit.

TwUI Text Engine Updates

I'm proposing to radically modify the underlying text engine that TwUI's text-based controls work on:

In progress:

  • Add TUITextDetector which can parse a TUITextStorage instance for "action-able" information, such as emails, dates, times, twitter usernames, hashtags, people, addresses, and so on. It would then contain an action for the data type, perhaps a delegate method call or a block.
  • Add NSTextView and NSText abilities to TUITextView.

Completed:

  • Convert TUIAttributedString into TUITextStorage, which, quite self explanatorily, will be a storage class for text, and its modifiers (font, size, alignment, style, line break, etc,).
  • Refactor TUITextRenderer slightly, into a class that renders a TUITextStorage and execute TUITextDetector actions.
  • Rebuild TUITextView to become a subclass of TUIScrollView, like iOS, and hold an internal TUITextRenderer, abstracting these features into a superficial API that can be easily used.
  • Rebuild TUITextField to remove dependency on TUITextView and hold an internal TUITextRenderer, and again, abstract these features into a superficial API.
  • Leverage TUILabel and TUITextField, but leave editing ability only to TUITextField.

Are there any suggestions/complaints/comments on these proposed changes?

TUIScrollView only responds to contentInset's top value

It can be reproduced by adding the following line to the ExampleScrollView.m:

_scrollView.contentInset = TUIEdgeInsetsMake(10, 10, 10, 10);

It's supposed to enlarge the scrolling area by 10 points at each edge. However we can only see the extra space at top.

New component TUISplitView

Before starting to work on something similar, I wanted to gather some opinions and advices.

Is this something that may find its way into the TwUI framework if correctly implemented?
From a class design point of view, should we try to resemble the Apple implementation or others which come to your minds?

I will develop it anyway since I need it for a personal project, because NSSplitView doesn't perform as well as I'd like. But first I wanted to check if you guys were interested so I would try to build something solid, and not just a quick hack.

TUITableView Inconsistent scrolling behavior with maintainContentOffsetAfterReload

I already talked about this bug to @jspahrsummers on twitter, but I thought it would be better to open an issue about it here.
If the maintainContentOffsetAfterReload is set the tableview doesn't resize as expected. For example in the example application, try to resize the window from the top border and you will see that content doesn't automatically scroll.
Instead if if set the property to FALSE it works as expected

TUITextRenderer antialiasing

For some reason, text rendered on my MacBook Pro's screen looks quite "thin" and "weak", whereas on my LED display, it looks normal, in line with the rest of Mac OS X. I believe this is an issue with CGContextSetShouldSmoothFonts being turned on, where a CALayer doesn't have sufficient RGBA information about the text's background to draw it "smoothly". Is there a way to fix this?

NSView inside TUIScrollView overlaps the scroll view konb

I embedded a NSImageVIew in TUIScrollView in order to display animated GIFs, however the NSImageView overlaps the scroll view knob.

I think it's due to the implementation that NSViews (TUIViewNSViewContainer) must be on top of its sibling TUIViews. Of course I can switch to the traditional 'NS' way (by using a NSScrollView) in my case. I'm just wondering if there's other way around, or can we get rid of the NSView hierarchy limitation somehow?

Crash on _cleanupResponderChain in TUIView?

I'm currently working with a TUITableView and having some issues. When I start scrolling, the app locks up (crashes) and it is because of line 747 or so of TUIView:

} else if([_textRenderers containsObject:[window firstResponder]]) {

The _textRenderers object seems to be the issue. I believe it is being released before accessed.

Any ideas? I'm implementing this very similarly to the Example Project, yet having issues. I'm slowly moving all of my code into the example project to see where exactly I'm running into the issue. I'll be sure to let you know when I figure it out (If I can!)

TUIStyledView merge

Would it not be better to merge TUIStyledView into TUIView? It's a very think wrapper just for two properties.

TUIControl tabbing and focus rings

  • When using AppKit, tab and shift-tab allow you to navigate the responder chain for controls, but this doesn't happen on TUIKit.
  • Focus rings are nonexistant on TUIKit, and I think we need them to actually indicate the focused element.

How to host raw CALayers inside TUIView?

Hello,
This is not an issue (is there a better place to ask a question) but an HowTo request.
How to host plain CALayers (and animate them) inside a TUIView?

Thanks and regards,

TUIPopover Deallocation Issues

TUIPopover functions fine normally with a simple TUIView as it's content view controller, but when subviews, especially tableviews, are added to said content view controller, TUIPopover begins to release wildly in one of a few ways I've observed (interestingly enough, this is fixed by #143):

  1. (Using only a tableview), the window is closed, it's contentView is then nilled out (unnecessarily, IMHO), which then causes a -release to be sent twice to the contentView.

  2. (Sans tableview), the window is closed, sent the proper release messages, then TUIPopover sends it a second release (a release to an unallocated pointer).

  3. (Sans TableView, with a background view), the window is closed, sent the proper release message, then TUIPopover sends it's background view an extra release.

TUIControl multitouch support + TUIEventRecognizer

Currently, TUIControl lacks multitouch handling support (well, TUIResponder has it, but TUIControl does not support tracking it). I think TwUI should.

TwUI could also use something like a TUIEventRecognizer with respective subclasses (like Velvet has) to make multitouch events easier to work with.

Contributions?

I will use TwUI in a private project.

I noticed that the performance many TUIControls like TUIImageView could be greatly improved by using CALayer.contents instead of drawRect:.
No idea why at that time people decided to use drawRect:. The whole idea of this project is to render on the GPU rather than the CPU.

Ironically, this causes many apps that were built with TwUI to have very low frame rates, especially when resizing, since many of the views are completely redrawn. Try resizing the window of Wunderlist or Kickoff, terrible.

I know this fork is feature-frozen.
Should I create a pull-request when I'm done or just keep it to myself?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.