├── .gitignore ├── Classes ├── iArrayController.h ├── iArrayController.m ├── iHeaderStyle.h ├── iHeaderStyle.m ├── iTableStyle.h └── iTableStyle.m ├── GraphFiles ├── bootstrap.min.css ├── bootstrap.min.js ├── index.html └── jquery-1.7.1.min.js ├── LICENSE ├── PieFiles ├── fullpie-index.html ├── fullpie-index.js ├── fullpie-style.css ├── jquery-1.7.1.min.js ├── pie-index.html ├── pie-index.js ├── pie-normalize.css └── pie-style.css ├── README.md ├── iTunes Table Header.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── iTunes Table Header.xccheckout │ └── xcuserdata │ │ └── jon.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── jon.xcuserdatad │ └── xcschemes │ ├── iTunes Table Header.xcscheme │ └── xcschememanagement.plist ├── iTunes Table Header ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ ├── Credits.rtf │ └── MainMenu.xib ├── GraphController.h ├── GraphController.m ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── en.lproj │ ├── Credits.rtf │ └── InfoPlist.strings ├── iArrayController.h ├── iArrayController.m ├── iHeaderStyle.h ├── iHeaderStyle.m ├── iTableStyle.h ├── iTableStyle.m ├── iTunes Table Header-Info.plist ├── iTunes Table Header-Prefix.pch ├── iTunes Table Header.entitlements └── main.m ├── iTunes Table HeaderTests ├── en.lproj │ └── InfoPlist.strings ├── iTunes Table HeaderTests-Info.plist └── iTunes_Table_HeaderTests.m └── screenshot ├── 2.png ├── HorizontalGraph.png ├── graph.png └── iTunesWindow.png /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /Classes/iArrayController.h: -------------------------------------------------------------------------------- 1 | // 2 | // iArrayController.h 3 | // iTunes Table Header 4 | // 5 | // Created by Jon Brown on 11/1/13. 6 | // Copyright (c) 2013 Jon Brown Designs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface iArrayController : NSArrayController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Classes/iArrayController.m: -------------------------------------------------------------------------------- 1 | // 2 | // iArrayController.m 3 | // iTunes Table Header 4 | // 5 | // Created by Jon Brown on 11/1/13. 6 | // Copyright (c) 2013 Jon Brown Designs. All rights reserved. 7 | // 8 | 9 | #import "iArrayController.h" 10 | 11 | @implementation iArrayController 12 | 13 | -(void)awakeFromNib 14 | { 15 | //Sorting at startup 16 | NSSortDescriptor* SortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"artist" 17 | ascending:YES selector:@selector(compare:)] autorelease]; 18 | [self setSortDescriptors:[NSArray arrayWithObject:SortDescriptor]]; 19 | 20 | //need to initialize the array 21 | [super awakeFromNib]; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Classes/iHeaderStyle.h: -------------------------------------------------------------------------------- 1 | // 2 | // iHeaderStyle.h 3 | // iTunes Table Header 4 | // 5 | // Created by Jon Brown on 11/1/13. 6 | // Copyright (c) 2013 Jon Brown Designs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface iHeaderStyle : NSTableHeaderCell { 12 | NSMutableDictionary *attrs; 13 | } 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Classes/iHeaderStyle.m: -------------------------------------------------------------------------------- 1 | // 2 | // iHeaderStyle.m 3 | // iTunes Table Header 4 | // 5 | // Created by Jon Brown on 11/1/13. 6 | // Copyright (c) 2013 Jon Brown Designs. All rights reserved. 7 | // 8 | 9 | #import "iHeaderStyle.h" 10 | 11 | @implementation iHeaderStyle 12 | 13 | - (id)initTextCell:(NSString *)text 14 | { 15 | if (self = [super initTextCell:text]) { 16 | 17 | if (text == nil || [text isEqualToString:@""]) { 18 | [self setTitle:@"Title"]; 19 | } 20 | 21 | attrs = [[NSMutableDictionary dictionaryWithDictionary: 22 | [[self attributedStringValue] 23 | attributesAtIndex:0 24 | effectiveRange:NULL]] 25 | mutableCopy]; 26 | return self; 27 | } 28 | return nil; 29 | } 30 | 31 | - (void)drawWithFrame:(CGRect)cellFrame 32 | highlighted:(BOOL)isHighlighted 33 | inView:(NSView *)view 34 | { 35 | 36 | CGRect fillRect, borderRect; 37 | CGRectDivide(cellFrame, &borderRect, &fillRect, 1.0, CGRectMaxYEdge); 38 | 39 | NSGradient *gradient = [[NSGradient alloc] 40 | initWithStartingColor:[NSColor whiteColor] 41 | endingColor:[NSColor colorWithDeviceWhite:0.9 alpha:1.0]]; 42 | [gradient drawInRect:fillRect angle:90.0]; 43 | [gradient release]; 44 | 45 | 46 | if (isHighlighted) { 47 | [[NSColor colorWithDeviceWhite:0.0 alpha:0.1] set]; 48 | NSRectFillUsingOperation(fillRect, NSCompositeSourceOver); 49 | } 50 | 51 | [[NSColor colorWithDeviceWhite:0.8 alpha:1.0] set]; 52 | NSRectFill(borderRect); 53 | 54 | 55 | [self drawInteriorWithFrame:CGRectInset(fillRect, 0.0, 1.0) inView:view]; 56 | 57 | 58 | // Draw the column divider. 59 | [[NSColor lightGrayColor] set]; 60 | NSRect _dividerRect = NSMakeRect(cellFrame.origin.x + cellFrame.size.width -1, 0, 1,cellFrame.size.height); 61 | NSRectFill(_dividerRect); 62 | 63 | 64 | } 65 | 66 | 67 | - (void)drawWithFrame:(CGRect)cellFrame inView:(NSView *)view 68 | { 69 | [self drawWithFrame:cellFrame highlighted:NO inView:view]; 70 | } 71 | 72 | - (void)highlight:(BOOL)isHighlighted 73 | withFrame:(NSRect)cellFrame 74 | inView:(NSView *)view 75 | { 76 | [self drawWithFrame:cellFrame highlighted:isHighlighted inView:view]; 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /Classes/iTableStyle.h: -------------------------------------------------------------------------------- 1 | // 2 | // iTableStyle.h 3 | // iTunes Table Header 4 | // 5 | // Created by Jon Brown on 11/1/13. 6 | // Copyright (c) 2013 Jon Brown Designs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface iTableStyle : NSTableView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Classes/iTableStyle.m: -------------------------------------------------------------------------------- 1 | // 2 | // iTableStyle.m 3 | // iTunes Table Header 4 | // 5 | // Created by Jon Brown on 11/1/13. 6 | // Copyright (c) 2013 Jon Brown Designs. All rights reserved. 7 | // 8 | 9 | #import "iTableStyle.h" 10 | 11 | @implementation iTableStyle 12 | 13 | - (void)highlightSelectionInClipRect:(NSRect)theClipRect 14 | { 15 | 16 | // this method is asking us to draw the hightlights for 17 | // all of the selected rows that are visible inside theClipRect 18 | 19 | // 1. get the range of row indexes that are currently visible 20 | // 2. get a list of selected rows 21 | // 3. iterate over the visible rows and if their index is selected 22 | // 4. draw our custom highlight in the rect of that row. 23 | 24 | NSRange aVisibleRowIndexes = [self rowsInRect:theClipRect]; 25 | NSIndexSet* aSelectedRowIndexes = [self selectedRowIndexes]; 26 | long aRow = aVisibleRowIndexes.location; 27 | long anEndRow = aRow + aVisibleRowIndexes.length; 28 | NSGradient* gradient; 29 | NSColor* pathColor; 30 | 31 | // if the view is focused, use highlight color, otherwise use the out-of-focus highlight color 32 | if (self == [[self window] firstResponder] && [[self window] isMainWindow] && [[self window] isKeyWindow]) 33 | { 34 | 35 | gradient = [[[NSGradient alloc] initWithColorsAndLocations: 36 | [NSColor colorWithDeviceRed:(float)128/255 green:(float)157/255 blue:(float)194/255 alpha:1.0], 0.0, 37 | [NSColor colorWithDeviceRed:(float)128/255 green:(float)157/255 blue:(float)194/255 alpha:1.0], 1.0, nil] retain]; 38 | 39 | pathColor = [[NSColor colorWithDeviceRed:(float)128/255 green:(float)157/255 blue:(float)194/255 alpha:1.0] retain]; 40 | 41 | } 42 | else 43 | { 44 | 45 | gradient = [[[NSGradient alloc] initWithColorsAndLocations: 46 | [NSColor colorWithDeviceRed:(float)186/255 green:(float)192/255 blue:(float)203/255 alpha:1.0], 0.0, 47 | [NSColor colorWithDeviceRed:(float)186/255 green:(float)192/255 blue:(float)203/255 alpha:1.0], 1.0, nil] retain]; //160 80 48 | 49 | pathColor = [[NSColor colorWithDeviceRed:(float)186/255 green:(float)192/255 blue:(float)203/255 alpha:1.0] retain]; 50 | 51 | } 52 | 53 | // draw highlight for the visible, selected rows 54 | 55 | for (aRow; aRow < anEndRow; aRow++) { 56 | 57 | if([aSelectedRowIndexes containsIndex:aRow]) 58 | { 59 | NSRect aRowRect = NSInsetRect([self rectOfRow:aRow], 0, 0); //first is horizontal, second is vertical 60 | NSBezierPath * path = [NSBezierPath bezierPathWithRect:aRowRect]; //6.0 61 | 62 | [gradient drawInBezierPath:path angle:90]; 63 | 64 | } 65 | } 66 | 67 | } 68 | 69 | 70 | 71 | 72 | - (id)_highlightColorForCell:(NSCell *)cell 73 | { 74 | // we need to override this to return nil 75 | // or we'll see the default selection rectangle when the app is running 76 | // in any OS before leopard 77 | 78 | // you can also return a color if you simply want to change the table's default selection color 79 | return nil; 80 | } 81 | 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /GraphFiles/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.0.2 by @fat and @mdo 3 | * Copyright 2013 Twitter, Inc. 4 | * Licensed under http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Designed and built with all the love in the world by @mdo and @fat. 7 | */ 8 | 9 | if("undefined"==typeof jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]');if(a.length){var b=this.$element.find("input").prop("checked",!this.$element.hasClass("active")).trigger("change");"radio"===b.prop("type")&&a.find(".active").removeClass("active")}this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(''}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery); -------------------------------------------------------------------------------- /GraphFiles/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | 21 | 22 | 23 | 24 | 207 | 208 | 209 |
210 |
Cool Graph
211 | 212 |
213 |
Item 1
214 |
Item 2
215 |
Item 3
216 |
217 | 218 |
219 | 220 |

Item 1

221 |

Item 2

222 |

Item 3

223 | 224 | 225 |
226 |
227 | 228 | 229 | 264 | 265 | 266 | 267 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Jon Brown 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /PieFiles/fullpie-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /PieFiles/fullpie-index.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | myFunction3(0,0,0,'','',''); 3 | }); 4 | 5 | /*! 6 | * jquery.drawPieChart.js 7 | * Version: 0.3(Beta) 8 | * Inspired by Chart.js(http://www.chartjs.org/) 9 | * 10 | * Copyright 2013 hiro 11 | * https://github.com/githiro/drawPieChart 12 | * Released under the MIT license. 13 | */ 14 | ;(function($, undefined) { 15 | $.fn.drawPieChart = function(data, options) { 16 | var $this = this, 17 | W = $this.width(), 18 | H = $this.height(), 19 | centerX = W/2, 20 | centerY = H/2, 21 | cos = Math.cos, 22 | sin = Math.sin, 23 | PI = Math.PI, 24 | settings = $.extend({ 25 | segmentShowStroke : true, 26 | segmentStrokeColor : "#fff", 27 | segmentStrokeWidth : 1, 28 | baseColor: "#fff", 29 | baseOffset: 15, 30 | edgeOffset: 30,//offset from edge of $this 31 | pieSegmentGroupClass: "pieSegmentGroup", 32 | pieSegmentClass: "pieSegment", 33 | lightPiesOffset: 12,//lighten pie's width 34 | lightPiesOpacity: .3,//lighten pie's default opacity 35 | lightPieClass: "lightPie", 36 | animation : true, 37 | animationSteps : 90, 38 | animationEasing : "easeInOutExpo", 39 | tipOffsetX: -15, 40 | tipOffsetY: -45, 41 | tipClass: "pieTip", 42 | beforeDraw: function(){ }, 43 | afterDrawed : function(){ }, 44 | onPieMouseenter : function(e,data){ }, 45 | onPieMouseleave : function(e,data){ }, 46 | onPieClick : function(e,data){ } 47 | }, options), 48 | animationOptions = { 49 | linear : function (t){ 50 | return t; 51 | }, 52 | easeInOutExpo: function (t) { 53 | var v = t<.5 ? 8*t*t*t*t : 1-8*(--t)*t*t*t; 54 | return (v>1) ? 1 : v; 55 | } 56 | }, 57 | requestAnimFrame = function(){ 58 | return window.requestAnimationFrame || 59 | window.webkitRequestAnimationFrame || 60 | window.mozRequestAnimationFrame || 61 | window.oRequestAnimationFrame || 62 | window.msRequestAnimationFrame || 63 | function(callback) { 64 | window.setTimeout(callback, 1000 / 60); 65 | }; 66 | }(); 67 | 68 | var $wrapper = $('').appendTo($this); 69 | var $groups = [], 70 | $pies = [], 71 | $lightPies = [], 72 | easingFunction = animationOptions[settings.animationEasing], 73 | pieRadius = Min([H/2,W/2]) - settings.edgeOffset, 74 | segmentTotal = 0; 75 | 76 | //Draw base circle 77 | var drawBasePie = function(){ 78 | var base = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); 79 | var $base = $(base).appendTo($wrapper); 80 | base.setAttribute("cx", centerX); 81 | base.setAttribute("cy", centerY); 82 | base.setAttribute("r", pieRadius+settings.baseOffset); 83 | base.setAttribute("fill", settings.baseColor); 84 | }(); 85 | 86 | //Set up pie segments wrapper 87 | var pathGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g'); 88 | var $pathGroup = $(pathGroup).appendTo($wrapper); 89 | $pathGroup[0].setAttribute("opacity",0); 90 | 91 | //Set up tooltip 92 | var $tip = $('
').appendTo('body').hide(), 93 | tipW = $tip.width(), 94 | tipH = $tip.height(); 95 | 96 | for (var i = 0, len = data.length; i < len; i++){ 97 | segmentTotal += data[i].value; 98 | var g = document.createElementNS('http://www.w3.org/2000/svg', 'g'); 99 | g.setAttribute("data-order", i); 100 | g.setAttribute("class", settings.pieSegmentGroupClass); 101 | $groups[i] = $(g).appendTo($pathGroup); 102 | $groups[i] 103 | .on("mouseenter", pathMouseEnter) 104 | .on("mouseleave", pathMouseLeave) 105 | .on("mousemove", pathMouseMove) 106 | .on("click", pathClick); 107 | 108 | var p = document.createElementNS('http://www.w3.org/2000/svg', 'path'); 109 | p.setAttribute("stroke-width", settings.segmentStrokeWidth); 110 | p.setAttribute("stroke", settings.segmentStrokeColor); 111 | p.setAttribute("stroke-miterlimit", 2); 112 | p.setAttribute("fill", data[i].color); 113 | p.setAttribute("class", settings.pieSegmentClass); 114 | $pies[i] = $(p).appendTo($groups[i]); 115 | 116 | var lp = document.createElementNS('http://www.w3.org/2000/svg', 'path'); 117 | lp.setAttribute("stroke-width", settings.segmentStrokeWidth); 118 | lp.setAttribute("stroke", settings.segmentStrokeColor); 119 | lp.setAttribute("stroke-miterlimit", 2); 120 | lp.setAttribute("fill", data[i].color); 121 | lp.setAttribute("opacity", settings.lightPiesOpacity); 122 | lp.setAttribute("class", settings.lightPieClass); 123 | $lightPies[i] = $(lp).appendTo($groups[i]); 124 | } 125 | 126 | settings.beforeDraw.call($this); 127 | //Animation start 128 | triggerAnimation(); 129 | 130 | function pathMouseEnter(e){ 131 | var index = $(this).data().order; 132 | $tip.text(data[index].title + ": " + data[index].value).fadeIn(200); 133 | if ($groups[index][0].getAttribute("data-active") !== "active"){ 134 | $lightPies[index].animate({opacity: .8}, 180); 135 | } 136 | settings.onPieMouseenter.apply($(this),[e,data]); 137 | } 138 | function pathMouseLeave(e){ 139 | var index = $(this).data().order; 140 | $tip.hide(); 141 | if ($groups[index][0].getAttribute("data-active") !== "active"){ 142 | $lightPies[index].animate({opacity: settings.lightPiesOpacity}, 100); 143 | } 144 | settings.onPieMouseleave.apply($(this),[e,data]); 145 | } 146 | function pathMouseMove(e){ 147 | $tip.css({ 148 | top: e.pageY + settings.tipOffsetY, 149 | left: e.pageX - $tip.width() / 2 + settings.tipOffsetX 150 | }); 151 | } 152 | function pathClick(e){ 153 | var index = $(this).data().order; 154 | var targetGroup = $groups[index][0]; 155 | for (var i = 0, len = data.length; i < len; i++){ 156 | if (i === index) continue; 157 | $groups[i][0].setAttribute("data-active",""); 158 | $lightPies[i].css({opacity: settings.lightPiesOpacity}); 159 | } 160 | if (targetGroup.getAttribute("data-active") === "active"){ 161 | targetGroup.setAttribute("data-active",""); 162 | $lightPies[index].css({opacity: .8}); 163 | } else { 164 | targetGroup.setAttribute("data-active","active"); 165 | $lightPies[index].css({opacity: 1}); 166 | } 167 | settings.onPieClick.apply($(this),[e,data]); 168 | } 169 | function drawPieSegments (animationDecimal){ 170 | var startRadius = -PI/2,//-90 degree 171 | rotateAnimation = 1; 172 | if (settings.animation) { 173 | rotateAnimation = animationDecimal;//count up between0~1 174 | } 175 | 176 | $pathGroup[0].setAttribute("opacity",animationDecimal); 177 | 178 | //draw each path 179 | for (var i = 0, len = data.length; i < len; i++){ 180 | var segmentAngle = rotateAnimation * ((data[i].value/segmentTotal) * (PI*2)),//start radian 181 | endRadius = startRadius + segmentAngle, 182 | largeArc = ((endRadius - startRadius) % (PI * 2)) > PI ? 1 : 0, 183 | startX = centerX + cos(startRadius) * pieRadius, 184 | startY = centerY + sin(startRadius) * pieRadius, 185 | endX = centerX + cos(endRadius) * pieRadius, 186 | endY = centerY + sin(endRadius) * pieRadius, 187 | startX2 = centerX + cos(startRadius) * (pieRadius + settings.lightPiesOffset), 188 | startY2 = centerY + sin(startRadius) * (pieRadius + settings.lightPiesOffset), 189 | endX2 = centerX + cos(endRadius) * (pieRadius + settings.lightPiesOffset), 190 | endY2 = centerY + sin(endRadius) * (pieRadius + settings.lightPiesOffset); 191 | var cmd = [ 192 | 'M', startX, startY,//Move pointer 193 | 'A', pieRadius, pieRadius, 0, largeArc, 1, endX, endY,//Draw outer arc path 194 | 'L', centerX, centerY,//Draw line to the center. 195 | 'Z'//Cloth path 196 | ]; 197 | var cmd2 = [ 198 | 'M', startX2, startY2, 199 | 'A', pieRadius + settings.lightPiesOffset, pieRadius + settings.lightPiesOffset, 0, largeArc, 1, endX2, endY2,//Draw outer arc path 200 | 'L', centerX, centerY, 201 | 'Z' 202 | ]; 203 | $pies[i][0].setAttribute("d",cmd.join(' ')); 204 | $lightPies[i][0].setAttribute("d", cmd2.join(' ')); 205 | startRadius += segmentAngle; 206 | } 207 | } 208 | 209 | var animFrameAmount = (settings.animation)? 1/settings.animationSteps : 1,//if settings.animationSteps is 10, animFrameAmount is 0.1 210 | animCount =(settings.animation)? 0 : 1; 211 | function triggerAnimation(){ 212 | if (settings.animation) { 213 | requestAnimFrame(animationLoop); 214 | } else { 215 | drawPieSegments(1); 216 | } 217 | } 218 | function animationLoop(){ 219 | animCount += animFrameAmount;//animCount start from 0, after "settings.animationSteps"-times executed, animCount reaches 1. 220 | drawPieSegments(easingFunction(animCount)); 221 | if (animCount < 1){ 222 | requestAnimFrame(arguments.callee); 223 | } else { 224 | settings.afterDrawed.call($this); 225 | } 226 | } 227 | function Max(arr){ 228 | return Math.max.apply(null, arr); 229 | } 230 | function Min(arr){ 231 | return Math.min.apply(null, arr); 232 | } 233 | return $this; 234 | }; 235 | })(jQuery); -------------------------------------------------------------------------------- /PieFiles/fullpie-style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | body { 6 | background: #222428; 7 | font-family: "Oswald", "Helvetica Newe", Helvetica, sans-serif; 8 | } 9 | .chart { 10 | width: 275px; 11 | height: 275px; 12 | margin-top: 0px; 13 | margin-left: auto; 14 | margin-right: auto; 15 | } 16 | .pieTip { 17 | position: absolute; 18 | float: left; 19 | min-width: 30px; 20 | max-width: 300px; 21 | padding: 5px 18px 6px; 22 | border-radius: 2px; 23 | background: rgba(255,255,255,.97); 24 | color: #444; 25 | font-size: 19px; 26 | text-shadow: 0 1px 0 #fff; 27 | text-transform: uppercase; 28 | text-align: center; 29 | line-height: 1.3; 30 | letter-spacing: .06em; 31 | box-shadow: 0 0 3px rgba(0,0,0,0.2), 0 1px 2px rgba(0,0,0,0.5); 32 | -webkit-transform: all .3s; 33 | -moz-transform: all .3s; 34 | -ms-transform: all .3s; 35 | -o-transform: all .3s; 36 | transform: all .3s; 37 | pointer-events: none; 38 | } 39 | .pieTip:after { 40 | position: absolute; 41 | left: 50%; 42 | bottom: -6px; 43 | content: ""; 44 | height: 0; 45 | margin: 0 0 0 -6px; 46 | border-right: 5px solid transparent; 47 | border-left: 5px solid transparent; 48 | border-top: 6px solid rgba(255,255,255,.95); 49 | line-height: 0; 50 | } 51 | .chart path { cursor: pointer; } -------------------------------------------------------------------------------- /PieFiles/pie-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | 22 | SVG Doughnut chart with animation and tooltip - CodePen 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
32 | 33 | 34 | 35 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /PieFiles/pie-index.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | myFunction2(0,0,0,'','',''); 3 | }); 4 | 5 | /*! 6 | * jquery.drawDoughnutChart.js 7 | * Version: 0.4.1(Beta) 8 | * Inspired by Chart.js(http://www.chartjs.org/) 9 | * 10 | * Copyright 2014 hiro 11 | * https://github.com/githiro/drawDoughnutChart 12 | * Released under the MIT license. 13 | * 14 | */ 15 | ;(function($, undefined) { 16 | $.fn.drawDoughnutChart = function(data, options) { 17 | var $this = this, 18 | W = $this.width(), 19 | H = $this.height(), 20 | centerX = W/2, 21 | centerY = H/2, 22 | cos = Math.cos, 23 | sin = Math.sin, 24 | PI = Math.PI, 25 | settings = $.extend({ 26 | segmentShowStroke : true, 27 | segmentStrokeColor : "#0C1013", 28 | segmentStrokeWidth : 1, 29 | baseColor: "rgba(0,0,0,0.5)", 30 | baseOffset: 4, 31 | edgeOffset : 10,//offset from edge of $this 32 | percentageInnerCutout : 75, 33 | animation : true, 34 | animationSteps : 90, 35 | animationEasing : "easeInOutExpo", 36 | animateRotate : true, 37 | tipOffsetX: -8, 38 | tipOffsetY: -45, 39 | tipClass: "doughnutTip", 40 | summaryClass: "doughnutSummary", 41 | summaryTitle: "TOTAL:", 42 | summaryTitleClass: "doughnutSummaryTitle", 43 | summaryNumberClass: "doughnutSummaryNumber", 44 | beforeDraw: function() { }, 45 | afterDrawed : function() { }, 46 | onPathEnter : function(e,data) { }, 47 | onPathLeave : function(e,data) { } 48 | }, options), 49 | animationOptions = { 50 | linear : function (t) { 51 | return t; 52 | }, 53 | easeInOutExpo: function (t) { 54 | var v = t<.5 ? 8*t*t*t*t : 1-8*(--t)*t*t*t; 55 | return (v>1) ? 1 : v; 56 | } 57 | }, 58 | requestAnimFrame = function() { 59 | return window.requestAnimationFrame || 60 | window.webkitRequestAnimationFrame || 61 | window.mozRequestAnimationFrame || 62 | window.oRequestAnimationFrame || 63 | window.msRequestAnimationFrame || 64 | function(callback) { 65 | window.setTimeout(callback, 1000 / 60); 66 | }; 67 | }(); 68 | 69 | settings.beforeDraw.call($this); 70 | 71 | var $svg = $('').appendTo($this), 72 | $paths = [], 73 | easingFunction = animationOptions[settings.animationEasing], 74 | doughnutRadius = Min([H / 2,W / 2]) - settings.edgeOffset, 75 | cutoutRadius = doughnutRadius * (settings.percentageInnerCutout / 100), 76 | segmentTotal = 0; 77 | 78 | //Draw base doughnut 79 | var baseDoughnutRadius = doughnutRadius + settings.baseOffset, 80 | baseCutoutRadius = cutoutRadius - settings.baseOffset; 81 | $(document.createElementNS('http://www.w3.org/2000/svg', 'path')) 82 | .attr({ 83 | "d": getHollowCirclePath(baseDoughnutRadius, baseCutoutRadius), 84 | "fill": settings.baseColor 85 | }) 86 | .appendTo($svg); 87 | 88 | //Set up pie segments wrapper 89 | var $pathGroup = $(document.createElementNS('http://www.w3.org/2000/svg', 'g')); 90 | $pathGroup.attr({opacity: 0}).appendTo($svg); 91 | 92 | //Set up tooltip 93 | var $tip = $('
').appendTo('body').hide(), 94 | tipW = $tip.width(), 95 | tipH = $tip.height(); 96 | 97 | //Set up center text area 98 | var summarySize = (cutoutRadius - (doughnutRadius - cutoutRadius)) * 2, 99 | $summary = $('
') 100 | .appendTo($this) 101 | .css({ 102 | width: summarySize + "px", 103 | height: summarySize + "px", 104 | "margin-left": -(summarySize / 2) + "px", 105 | "margin-top": -(summarySize / 2) + "px" 106 | }); 107 | var $summaryTitle = $('

' + settings.summaryTitle + '

').appendTo($summary); 108 | var $summaryNumber = $('

').appendTo($summary).css({opacity: 0}); 109 | 110 | for (var i = 0, len = data.length; i < len; i++) { 111 | segmentTotal += data[i].value; 112 | $paths[i] = $(document.createElementNS('http://www.w3.org/2000/svg', 'path')) 113 | .attr({ 114 | "stroke-width": settings.segmentStrokeWidth, 115 | "stroke": settings.segmentStrokeColor, 116 | "fill": data[i].color, 117 | "data-order": i 118 | }) 119 | .appendTo($pathGroup) 120 | .on("mouseenter", pathMouseEnter) 121 | .on("mouseleave", pathMouseLeave) 122 | .on("mousemove", pathMouseMove); 123 | } 124 | 125 | //Animation start 126 | animationLoop(drawPieSegments); 127 | 128 | //Functions 129 | function getHollowCirclePath(doughnutRadius, cutoutRadius) { 130 | //Calculate values for the path. 131 | //We needn't calculate startRadius, segmentAngle and endRadius, because base doughnut doesn't animate. 132 | var startRadius = -1.570,// -Math.PI/2 133 | segmentAngle = 6.2831,// 1 * ((99.9999/100) * (PI*2)), 134 | endRadius = 4.7131,// startRadius + segmentAngle 135 | startX = centerX + cos(startRadius) * doughnutRadius, 136 | startY = centerY + sin(startRadius) * doughnutRadius, 137 | endX2 = centerX + cos(startRadius) * cutoutRadius, 138 | endY2 = centerY + sin(startRadius) * cutoutRadius, 139 | endX = centerX + cos(endRadius) * doughnutRadius, 140 | endY = centerY + sin(endRadius) * doughnutRadius, 141 | startX2 = centerX + cos(endRadius) * cutoutRadius, 142 | startY2 = centerY + sin(endRadius) * cutoutRadius; 143 | var cmd = [ 144 | 'M', startX, startY, 145 | 'A', doughnutRadius, doughnutRadius, 0, 1, 1, endX, endY,//Draw outer circle 146 | 'Z',//Close path 147 | 'M', startX2, startY2,//Move pointer 148 | 'A', cutoutRadius, cutoutRadius, 0, 1, 0, endX2, endY2,//Draw inner circle 149 | 'Z' 150 | ]; 151 | cmd = cmd.join(' '); 152 | return cmd; 153 | }; 154 | function pathMouseEnter(e) { 155 | var order = $(this).data().order; 156 | $tip.text(data[order].title + ": " + data[order].value) 157 | .fadeIn(200); 158 | settings.onPathEnter.apply($(this),[e,data]); 159 | } 160 | function pathMouseLeave(e) { 161 | $tip.hide(); 162 | settings.onPathLeave.apply($(this),[e,data]); 163 | } 164 | function pathMouseMove(e) { 165 | $tip.css({ 166 | top: e.pageY + settings.tipOffsetY, 167 | left: e.pageX - $tip.width() / 2 + settings.tipOffsetX 168 | }); 169 | } 170 | function drawPieSegments (animationDecimal) { 171 | var startRadius = -PI / 2,//-90 degree 172 | rotateAnimation = 1; 173 | if (settings.animation && settings.animateRotate) rotateAnimation = animationDecimal;//count up between0~1 174 | 175 | drawDoughnutText(animationDecimal, segmentTotal); 176 | 177 | $pathGroup.attr("opacity", animationDecimal); 178 | 179 | //If data have only one value, we draw hollow circle(#1). 180 | if (data.length === 1 && (4.7122 < (rotateAnimation * ((data[0].value / segmentTotal) * (PI * 2)) + startRadius))) { 181 | $paths[0].attr("d", getHollowCirclePath(doughnutRadius, cutoutRadius)); 182 | return; 183 | } 184 | for (var i = 0, len = data.length; i < len; i++) { 185 | var segmentAngle = rotateAnimation * ((data[i].value / segmentTotal) * (PI * 2)), 186 | endRadius = startRadius + segmentAngle, 187 | largeArc = ((endRadius - startRadius) % (PI * 2)) > PI ? 1 : 0, 188 | startX = centerX + cos(startRadius) * doughnutRadius, 189 | startY = centerY + sin(startRadius) * doughnutRadius, 190 | endX2 = centerX + cos(startRadius) * cutoutRadius, 191 | endY2 = centerY + sin(startRadius) * cutoutRadius, 192 | endX = centerX + cos(endRadius) * doughnutRadius, 193 | endY = centerY + sin(endRadius) * doughnutRadius, 194 | startX2 = centerX + cos(endRadius) * cutoutRadius, 195 | startY2 = centerY + sin(endRadius) * cutoutRadius; 196 | var cmd = [ 197 | 'M', startX, startY,//Move pointer 198 | 'A', doughnutRadius, doughnutRadius, 0, largeArc, 1, endX, endY,//Draw outer arc path 199 | 'L', startX2, startY2,//Draw line path(this line connects outer and innner arc paths) 200 | 'A', cutoutRadius, cutoutRadius, 0, largeArc, 0, endX2, endY2,//Draw inner arc path 201 | 'Z'//Cloth path 202 | ]; 203 | $paths[i].attr("d", cmd.join(' ')); 204 | startRadius += segmentAngle; 205 | } 206 | } 207 | function drawDoughnutText(animationDecimal, segmentTotal) { 208 | $summaryNumber 209 | .css({opacity: animationDecimal}) 210 | .text((segmentTotal * animationDecimal).toFixed(0)); 211 | } 212 | function animateFrame(cnt, drawData) { 213 | var easeAdjustedAnimationPercent =(settings.animation)? CapValue(easingFunction(cnt), null, 0) : 1; 214 | drawData(easeAdjustedAnimationPercent); 215 | } 216 | function animationLoop(drawData) { 217 | var animFrameAmount = (settings.animation)? 1 / CapValue(settings.animationSteps, Number.MAX_VALUE, 1) : 1, 218 | cnt =(settings.animation)? 0 : 1; 219 | requestAnimFrame(function() { 220 | cnt += animFrameAmount; 221 | animateFrame(cnt, drawData); 222 | if (cnt <= 1) { 223 | requestAnimFrame(arguments.callee); 224 | } else { 225 | settings.afterDrawed.call($this); 226 | } 227 | }); 228 | } 229 | function Max(arr) { 230 | return Math.max.apply(null, arr); 231 | } 232 | function Min(arr) { 233 | return Math.min.apply(null, arr); 234 | } 235 | function isNumber(n) { 236 | return !isNaN(parseFloat(n)) && isFinite(n); 237 | } 238 | function CapValue(valueToCap, maxValue, minValue) { 239 | if (isNumber(maxValue) && valueToCap > maxValue) return maxValue; 240 | if (isNumber(minValue) && valueToCap < minValue) return minValue; 241 | return valueToCap; 242 | } 243 | return $this; 244 | }; 245 | })(jQuery); -------------------------------------------------------------------------------- /PieFiles/pie-normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0} 2 | -------------------------------------------------------------------------------- /PieFiles/pie-style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: #222428; 3 | 4 | } 5 | 6 | .chart { 7 | position: relative; 8 | width: 250px; 9 | height: 250px; 10 | margin-top: 10px; 11 | margin-left: auto; 12 | margin-right: auto; 13 | } 14 | 15 | .doughnutTip { 16 | position: absolute; 17 | min-width: 30px; 18 | max-width: 300px; 19 | padding: 5px 15px; 20 | border-radius: 1px; 21 | background: rgba(0, 0, 0, 0.8); 22 | color: #ddd; 23 | font-size: 17px; 24 | text-shadow: 0 1px 0 #000; 25 | text-transform: uppercase; 26 | text-align: center; 27 | line-height: 1.3; 28 | letter-spacing: .06em; 29 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); 30 | pointer-events: none; 31 | cursor: default; 32 | user-select: none; 33 | -webkit-user-select: none; 34 | } 35 | .doughnutTip::after { 36 | position: absolute; 37 | left: 50%; 38 | bottom: -6px; 39 | content: ""; 40 | height: 0; 41 | margin: 0 0 0 -6px; 42 | border-right: 5px solid transparent; 43 | border-left: 5px solid transparent; 44 | border-top: 6px solid rgba(0, 0, 0, 0.7); 45 | line-height: 0; 46 | cursor: default; 47 | user-select: none; 48 | -webkit-user-select: none; 49 | } 50 | 51 | .doughnutSummary { 52 | position: absolute; 53 | top: 50%; 54 | left: 50%; 55 | color: #d5d5d5; 56 | text-align: center; 57 | text-shadow: 0 -1px 0 #111; 58 | cursor: default; 59 | cursor: default; 60 | user-select: none; 61 | -webkit-user-select: none; 62 | } 63 | 64 | .doughnutSummaryTitle { 65 | position: absolute; 66 | top: 50%; 67 | width: 100%; 68 | margin-top: -27%; 69 | font-size: 16px; 70 | letter-spacing: .06em; 71 | cursor: default; 72 | user-select: none; 73 | -webkit-user-select: none; 74 | } 75 | 76 | .doughnutSummaryNumber { 77 | position: absolute; 78 | top: 50%; 79 | width: 100%; 80 | margin-top: -15%; 81 | font-size: 45px; 82 | cursor: default; 83 | user-select: none; 84 | -webkit-user-select: none; 85 | } 86 | 87 | .chart path:hover { 88 | opacity: 0.65; 89 | } 90 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Web Graph Controller 2 | =========================== 3 | 4 | A complete collection of subclasses and controller classes to make any WebView a custom iTunes style horizontal graph. You can style this graph with CSS all transitions and animations are done via CSS3. No images required. 5 | 6 | These graphs are generated by CSS & CSS SVG code only all values are passed via Javascript to a webview in your Cocoa project. 7 | 8 | ![ScreenShot](https://github.com/jonbrown21/Horizontal-Graph-Controller/blob/master/screenshot/2.png) 9 | 10 | GraphController 11 | =================== 12 | A subclass of WebView that calculates the sum of the NSTableView and feeds that as int variables into the WebView where CSS3 take the data and dynamically draw the graph. 13 | 14 | ![ScreenShot](https://raw.githubusercontent.com/jonbrown21/Horizontal-Graph-Controller/master/screenshot/graph.png) 15 | 16 | Sample Application - iTunes Graph Style 17 | =================== 18 | Included is a Sample Application that shows you how to connect all the pieces and allows you to play with the data in the tableview and see it drawn in the graph view below. Enjoy! 19 | 20 | Swift? 21 | =================== 22 | Interested in seeing this expand, improve and move to Swift? Pull / Push requests appreciated 23 | 24 | Attribution 25 | =================== 26 | https://github.com/githiro - For the CSS SVG Graph Code 27 | -------------------------------------------------------------------------------- /iTunes Table Header.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | FC54F39A1997304400609BB3 /* bootstrap.min.css in Resources */ = {isa = PBXBuildFile; fileRef = FC54F3961997304400609BB3 /* bootstrap.min.css */; }; 11 | FC54F39C1997304400609BB3 /* index.html in Resources */ = {isa = PBXBuildFile; fileRef = FC54F3981997304400609BB3 /* index.html */; }; 12 | FC575EC41A09B33B003D03DC /* fullpie-index.html in Resources */ = {isa = PBXBuildFile; fileRef = FC575EC11A09B33B003D03DC /* fullpie-index.html */; }; 13 | FC575EC51A09B33B003D03DC /* fullpie-index.js in Resources */ = {isa = PBXBuildFile; fileRef = FC575EC21A09B33B003D03DC /* fullpie-index.js */; }; 14 | FC575EC61A09B33B003D03DC /* fullpie-style.css in Resources */ = {isa = PBXBuildFile; fileRef = FC575EC31A09B33B003D03DC /* fullpie-style.css */; }; 15 | FC8AF60B184BE705000968FF /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FC8AF60A184BE705000968FF /* WebKit.framework */; }; 16 | FC8AF61F184BF6E5000968FF /* GraphController.m in Sources */ = {isa = PBXBuildFile; fileRef = FC8AF61E184BF6E5000968FF /* GraphController.m */; }; 17 | FCA119111A076E2C00791D17 /* pie-index.html in Resources */ = {isa = PBXBuildFile; fileRef = FCA1190D1A076E2C00791D17 /* pie-index.html */; }; 18 | FCA119121A076E2C00791D17 /* pie-index.js in Resources */ = {isa = PBXBuildFile; fileRef = FCA1190E1A076E2C00791D17 /* pie-index.js */; }; 19 | FCA119131A076E2C00791D17 /* pie-normalize.css in Resources */ = {isa = PBXBuildFile; fileRef = FCA1190F1A076E2C00791D17 /* pie-normalize.css */; }; 20 | FCA119141A076E2C00791D17 /* pie-style.css in Resources */ = {isa = PBXBuildFile; fileRef = FCA119101A076E2C00791D17 /* pie-style.css */; }; 21 | FCA119161A07700E00791D17 /* bootstrap.min.js in Resources */ = {isa = PBXBuildFile; fileRef = FC54F3971997304400609BB3 /* bootstrap.min.js */; }; 22 | FCA119171A07700E00791D17 /* jquery-1.7.1.min.js in Resources */ = {isa = PBXBuildFile; fileRef = FC54F3991997304400609BB3 /* jquery-1.7.1.min.js */; }; 23 | FCA119191A0771C300791D17 /* jquery-1.7.1.min.js in Resources */ = {isa = PBXBuildFile; fileRef = FCA119181A0771C300791D17 /* jquery-1.7.1.min.js */; }; 24 | FCEA069A1824966E004FDEE6 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FCEA06991824966E004FDEE6 /* Cocoa.framework */; }; 25 | FCEA06A41824966E004FDEE6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FCEA06A21824966E004FDEE6 /* InfoPlist.strings */; }; 26 | FCEA06A61824966E004FDEE6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = FCEA06A51824966E004FDEE6 /* main.m */; }; 27 | FCEA06AA1824966E004FDEE6 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = FCEA06A81824966E004FDEE6 /* Credits.rtf */; }; 28 | FCEA06AD1824966E004FDEE6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FCEA06AC1824966E004FDEE6 /* AppDelegate.m */; }; 29 | FCEA06B01824966E004FDEE6 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = FCEA06AE1824966E004FDEE6 /* MainMenu.xib */; }; 30 | FCEA06B21824966E004FDEE6 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FCEA06B11824966E004FDEE6 /* Images.xcassets */; }; 31 | FCEA06B91824966E004FDEE6 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FCEA06B81824966E004FDEE6 /* XCTest.framework */; }; 32 | FCEA06BA1824966E004FDEE6 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FCEA06991824966E004FDEE6 /* Cocoa.framework */; }; 33 | FCEA06C21824966E004FDEE6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FCEA06C01824966E004FDEE6 /* InfoPlist.strings */; }; 34 | FCEA06C41824966E004FDEE6 /* iTunes_Table_HeaderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = FCEA06C31824966E004FDEE6 /* iTunes_Table_HeaderTests.m */; }; 35 | FCEA06CF1824996B004FDEE6 /* iHeaderStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = FCEA06CE1824996B004FDEE6 /* iHeaderStyle.m */; }; 36 | FCEA06D21824A114004FDEE6 /* iTableStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = FCEA06D11824A114004FDEE6 /* iTableStyle.m */; }; 37 | FCEA06D51824ABF2004FDEE6 /* iArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = FCEA06D41824ABF2004FDEE6 /* iArrayController.m */; }; 38 | /* End PBXBuildFile section */ 39 | 40 | /* Begin PBXContainerItemProxy section */ 41 | FCEA06BB1824966E004FDEE6 /* PBXContainerItemProxy */ = { 42 | isa = PBXContainerItemProxy; 43 | containerPortal = FCEA068E1824966E004FDEE6 /* Project object */; 44 | proxyType = 1; 45 | remoteGlobalIDString = FCEA06951824966E004FDEE6; 46 | remoteInfo = "iTunes Table Header"; 47 | }; 48 | /* End PBXContainerItemProxy section */ 49 | 50 | /* Begin PBXFileReference section */ 51 | FC54F3961997304400609BB3 /* bootstrap.min.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = bootstrap.min.css; path = GraphFiles/bootstrap.min.css; sourceTree = ""; }; 52 | FC54F3971997304400609BB3 /* bootstrap.min.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = bootstrap.min.js; path = GraphFiles/bootstrap.min.js; sourceTree = ""; }; 53 | FC54F3981997304400609BB3 /* index.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = index.html; path = GraphFiles/index.html; sourceTree = ""; }; 54 | FC54F3991997304400609BB3 /* jquery-1.7.1.min.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = "jquery-1.7.1.min.js"; path = "GraphFiles/jquery-1.7.1.min.js"; sourceTree = ""; }; 55 | FC575EC11A09B33B003D03DC /* fullpie-index.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = "fullpie-index.html"; path = "PieFiles/fullpie-index.html"; sourceTree = ""; }; 56 | FC575EC21A09B33B003D03DC /* fullpie-index.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = "fullpie-index.js"; path = "PieFiles/fullpie-index.js"; sourceTree = ""; }; 57 | FC575EC31A09B33B003D03DC /* fullpie-style.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = "fullpie-style.css"; path = "PieFiles/fullpie-style.css"; sourceTree = ""; }; 58 | FC7D9D73182B44AD003D072C /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = Base; path = Base.lproj/Credits.rtf; sourceTree = ""; }; 59 | FC8AF60A184BE705000968FF /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; 60 | FC8AF61D184BF6E5000968FF /* GraphController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GraphController.h; sourceTree = ""; }; 61 | FC8AF61E184BF6E5000968FF /* GraphController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GraphController.m; sourceTree = ""; }; 62 | FCA1190D1A076E2C00791D17 /* pie-index.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = "pie-index.html"; path = "PieFiles/pie-index.html"; sourceTree = ""; }; 63 | FCA1190E1A076E2C00791D17 /* pie-index.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = "pie-index.js"; path = "PieFiles/pie-index.js"; sourceTree = ""; }; 64 | FCA1190F1A076E2C00791D17 /* pie-normalize.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = "pie-normalize.css"; path = "PieFiles/pie-normalize.css"; sourceTree = ""; }; 65 | FCA119101A076E2C00791D17 /* pie-style.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = "pie-style.css"; path = "PieFiles/pie-style.css"; sourceTree = ""; }; 66 | FCA119181A0771C300791D17 /* jquery-1.7.1.min.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = "jquery-1.7.1.min.js"; path = "PieFiles/jquery-1.7.1.min.js"; sourceTree = ""; }; 67 | FCEA06961824966E004FDEE6 /* iTunes Table Header.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "iTunes Table Header.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 68 | FCEA06991824966E004FDEE6 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 69 | FCEA069C1824966E004FDEE6 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 70 | FCEA069D1824966E004FDEE6 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 71 | FCEA069E1824966E004FDEE6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 72 | FCEA06A11824966E004FDEE6 /* iTunes Table Header-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "iTunes Table Header-Info.plist"; sourceTree = ""; }; 73 | FCEA06A31824966E004FDEE6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 74 | FCEA06A51824966E004FDEE6 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 75 | FCEA06A71824966E004FDEE6 /* iTunes Table Header-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "iTunes Table Header-Prefix.pch"; sourceTree = ""; }; 76 | FCEA06A91824966E004FDEE6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 77 | FCEA06AB1824966E004FDEE6 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 78 | FCEA06AC1824966E004FDEE6 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 79 | FCEA06AF1824966E004FDEE6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 80 | FCEA06B11824966E004FDEE6 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 81 | FCEA06B71824966E004FDEE6 /* iTunes Table HeaderTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "iTunes Table HeaderTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 82 | FCEA06B81824966E004FDEE6 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 83 | FCEA06BF1824966E004FDEE6 /* iTunes Table HeaderTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "iTunes Table HeaderTests-Info.plist"; sourceTree = ""; }; 84 | FCEA06C11824966E004FDEE6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 85 | FCEA06C31824966E004FDEE6 /* iTunes_Table_HeaderTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = iTunes_Table_HeaderTests.m; sourceTree = ""; }; 86 | FCEA06CD1824996B004FDEE6 /* iHeaderStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iHeaderStyle.h; sourceTree = ""; }; 87 | FCEA06CE1824996B004FDEE6 /* iHeaderStyle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = iHeaderStyle.m; sourceTree = ""; }; 88 | FCEA06D01824A114004FDEE6 /* iTableStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iTableStyle.h; sourceTree = ""; }; 89 | FCEA06D11824A114004FDEE6 /* iTableStyle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = iTableStyle.m; sourceTree = ""; }; 90 | FCEA06D31824ABF2004FDEE6 /* iArrayController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iArrayController.h; sourceTree = ""; }; 91 | FCEA06D41824ABF2004FDEE6 /* iArrayController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = iArrayController.m; sourceTree = ""; }; 92 | FCEA06D61824B051004FDEE6 /* iTunes Table Header.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "iTunes Table Header.entitlements"; sourceTree = ""; }; 93 | /* End PBXFileReference section */ 94 | 95 | /* Begin PBXFrameworksBuildPhase section */ 96 | FCEA06931824966E004FDEE6 /* Frameworks */ = { 97 | isa = PBXFrameworksBuildPhase; 98 | buildActionMask = 2147483647; 99 | files = ( 100 | FC8AF60B184BE705000968FF /* WebKit.framework in Frameworks */, 101 | FCEA069A1824966E004FDEE6 /* Cocoa.framework in Frameworks */, 102 | ); 103 | runOnlyForDeploymentPostprocessing = 0; 104 | }; 105 | FCEA06B41824966E004FDEE6 /* Frameworks */ = { 106 | isa = PBXFrameworksBuildPhase; 107 | buildActionMask = 2147483647; 108 | files = ( 109 | FCEA06BA1824966E004FDEE6 /* Cocoa.framework in Frameworks */, 110 | FCEA06B91824966E004FDEE6 /* XCTest.framework in Frameworks */, 111 | ); 112 | runOnlyForDeploymentPostprocessing = 0; 113 | }; 114 | /* End PBXFrameworksBuildPhase section */ 115 | 116 | /* Begin PBXGroup section */ 117 | FC7613D31A08CCC300C528B7 /* Custom Header */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | FCEA06D01824A114004FDEE6 /* iTableStyle.h */, 121 | FCEA06D11824A114004FDEE6 /* iTableStyle.m */, 122 | FCEA06CD1824996B004FDEE6 /* iHeaderStyle.h */, 123 | FCEA06CE1824996B004FDEE6 /* iHeaderStyle.m */, 124 | FCEA06D31824ABF2004FDEE6 /* iArrayController.h */, 125 | FCEA06D41824ABF2004FDEE6 /* iArrayController.m */, 126 | ); 127 | name = "Custom Header"; 128 | path = "iTunes Table Header"; 129 | sourceTree = ""; 130 | }; 131 | FC7613DE1A08D19500C528B7 /* FullPie */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | FC575EC11A09B33B003D03DC /* fullpie-index.html */, 135 | FC575EC21A09B33B003D03DC /* fullpie-index.js */, 136 | FC575EC31A09B33B003D03DC /* fullpie-style.css */, 137 | ); 138 | name = FullPie; 139 | sourceTree = ""; 140 | }; 141 | FC8AF61C184BF399000968FF /* Graph */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | FC54F3961997304400609BB3 /* bootstrap.min.css */, 145 | FC54F3971997304400609BB3 /* bootstrap.min.js */, 146 | FC54F3981997304400609BB3 /* index.html */, 147 | FC54F3991997304400609BB3 /* jquery-1.7.1.min.js */, 148 | ); 149 | name = Graph; 150 | sourceTree = ""; 151 | }; 152 | FCA119151A076E3200791D17 /* PieGraph */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | FCA119181A0771C300791D17 /* jquery-1.7.1.min.js */, 156 | FCA1190D1A076E2C00791D17 /* pie-index.html */, 157 | FCA1190E1A076E2C00791D17 /* pie-index.js */, 158 | FCA1190F1A076E2C00791D17 /* pie-normalize.css */, 159 | FCA119101A076E2C00791D17 /* pie-style.css */, 160 | ); 161 | name = PieGraph; 162 | sourceTree = ""; 163 | }; 164 | FCEA068D1824966E004FDEE6 = { 165 | isa = PBXGroup; 166 | children = ( 167 | FC7613DE1A08D19500C528B7 /* FullPie */, 168 | FC7613D31A08CCC300C528B7 /* Custom Header */, 169 | FCA119151A076E3200791D17 /* PieGraph */, 170 | FC8AF61C184BF399000968FF /* Graph */, 171 | FCEA069F1824966E004FDEE6 /* iTunes Table Header */, 172 | FCEA06BD1824966E004FDEE6 /* iTunes Table HeaderTests */, 173 | FCEA06981824966E004FDEE6 /* Frameworks */, 174 | FCEA06971824966E004FDEE6 /* Products */, 175 | ); 176 | sourceTree = ""; 177 | }; 178 | FCEA06971824966E004FDEE6 /* Products */ = { 179 | isa = PBXGroup; 180 | children = ( 181 | FCEA06961824966E004FDEE6 /* iTunes Table Header.app */, 182 | FCEA06B71824966E004FDEE6 /* iTunes Table HeaderTests.xctest */, 183 | ); 184 | name = Products; 185 | sourceTree = ""; 186 | }; 187 | FCEA06981824966E004FDEE6 /* Frameworks */ = { 188 | isa = PBXGroup; 189 | children = ( 190 | FC8AF60A184BE705000968FF /* WebKit.framework */, 191 | FCEA06991824966E004FDEE6 /* Cocoa.framework */, 192 | FCEA06B81824966E004FDEE6 /* XCTest.framework */, 193 | FCEA069B1824966E004FDEE6 /* Other Frameworks */, 194 | ); 195 | name = Frameworks; 196 | sourceTree = ""; 197 | }; 198 | FCEA069B1824966E004FDEE6 /* Other Frameworks */ = { 199 | isa = PBXGroup; 200 | children = ( 201 | FCEA069C1824966E004FDEE6 /* AppKit.framework */, 202 | FCEA069D1824966E004FDEE6 /* CoreData.framework */, 203 | FCEA069E1824966E004FDEE6 /* Foundation.framework */, 204 | ); 205 | name = "Other Frameworks"; 206 | sourceTree = ""; 207 | }; 208 | FCEA069F1824966E004FDEE6 /* iTunes Table Header */ = { 209 | isa = PBXGroup; 210 | children = ( 211 | FCEA06D61824B051004FDEE6 /* iTunes Table Header.entitlements */, 212 | FCEA06AB1824966E004FDEE6 /* AppDelegate.h */, 213 | FCEA06AC1824966E004FDEE6 /* AppDelegate.m */, 214 | FC8AF61D184BF6E5000968FF /* GraphController.h */, 215 | FC8AF61E184BF6E5000968FF /* GraphController.m */, 216 | FCEA06AE1824966E004FDEE6 /* MainMenu.xib */, 217 | FCEA06B11824966E004FDEE6 /* Images.xcassets */, 218 | FCEA06A01824966E004FDEE6 /* Supporting Files */, 219 | ); 220 | path = "iTunes Table Header"; 221 | sourceTree = ""; 222 | }; 223 | FCEA06A01824966E004FDEE6 /* Supporting Files */ = { 224 | isa = PBXGroup; 225 | children = ( 226 | FCEA06A11824966E004FDEE6 /* iTunes Table Header-Info.plist */, 227 | FCEA06A21824966E004FDEE6 /* InfoPlist.strings */, 228 | FCEA06A51824966E004FDEE6 /* main.m */, 229 | FCEA06A71824966E004FDEE6 /* iTunes Table Header-Prefix.pch */, 230 | FCEA06A81824966E004FDEE6 /* Credits.rtf */, 231 | ); 232 | name = "Supporting Files"; 233 | sourceTree = ""; 234 | }; 235 | FCEA06BD1824966E004FDEE6 /* iTunes Table HeaderTests */ = { 236 | isa = PBXGroup; 237 | children = ( 238 | FCEA06C31824966E004FDEE6 /* iTunes_Table_HeaderTests.m */, 239 | FCEA06BE1824966E004FDEE6 /* Supporting Files */, 240 | ); 241 | path = "iTunes Table HeaderTests"; 242 | sourceTree = ""; 243 | }; 244 | FCEA06BE1824966E004FDEE6 /* Supporting Files */ = { 245 | isa = PBXGroup; 246 | children = ( 247 | FCEA06BF1824966E004FDEE6 /* iTunes Table HeaderTests-Info.plist */, 248 | FCEA06C01824966E004FDEE6 /* InfoPlist.strings */, 249 | ); 250 | name = "Supporting Files"; 251 | sourceTree = ""; 252 | }; 253 | /* End PBXGroup section */ 254 | 255 | /* Begin PBXNativeTarget section */ 256 | FCEA06951824966E004FDEE6 /* iTunes Table Header */ = { 257 | isa = PBXNativeTarget; 258 | buildConfigurationList = FCEA06C71824966E004FDEE6 /* Build configuration list for PBXNativeTarget "iTunes Table Header" */; 259 | buildPhases = ( 260 | FCEA06921824966E004FDEE6 /* Sources */, 261 | FCEA06931824966E004FDEE6 /* Frameworks */, 262 | FCEA06941824966E004FDEE6 /* Resources */, 263 | ); 264 | buildRules = ( 265 | ); 266 | dependencies = ( 267 | ); 268 | name = "iTunes Table Header"; 269 | productName = "iTunes Table Header"; 270 | productReference = FCEA06961824966E004FDEE6 /* iTunes Table Header.app */; 271 | productType = "com.apple.product-type.application"; 272 | }; 273 | FCEA06B61824966E004FDEE6 /* iTunes Table HeaderTests */ = { 274 | isa = PBXNativeTarget; 275 | buildConfigurationList = FCEA06CA1824966E004FDEE6 /* Build configuration list for PBXNativeTarget "iTunes Table HeaderTests" */; 276 | buildPhases = ( 277 | FCEA06B31824966E004FDEE6 /* Sources */, 278 | FCEA06B41824966E004FDEE6 /* Frameworks */, 279 | FCEA06B51824966E004FDEE6 /* Resources */, 280 | ); 281 | buildRules = ( 282 | ); 283 | dependencies = ( 284 | FCEA06BC1824966E004FDEE6 /* PBXTargetDependency */, 285 | ); 286 | name = "iTunes Table HeaderTests"; 287 | productName = "iTunes Table HeaderTests"; 288 | productReference = FCEA06B71824966E004FDEE6 /* iTunes Table HeaderTests.xctest */; 289 | productType = "com.apple.product-type.bundle.unit-test"; 290 | }; 291 | /* End PBXNativeTarget section */ 292 | 293 | /* Begin PBXProject section */ 294 | FCEA068E1824966E004FDEE6 /* Project object */ = { 295 | isa = PBXProject; 296 | attributes = { 297 | LastUpgradeCheck = 0500; 298 | ORGANIZATIONNAME = "Jon Brown Designs"; 299 | TargetAttributes = { 300 | FCEA06951824966E004FDEE6 = { 301 | SystemCapabilities = { 302 | com.apple.Sandbox = { 303 | enabled = 0; 304 | }; 305 | }; 306 | }; 307 | FCEA06B61824966E004FDEE6 = { 308 | TestTargetID = FCEA06951824966E004FDEE6; 309 | }; 310 | }; 311 | }; 312 | buildConfigurationList = FCEA06911824966E004FDEE6 /* Build configuration list for PBXProject "iTunes Table Header" */; 313 | compatibilityVersion = "Xcode 3.2"; 314 | developmentRegion = English; 315 | hasScannedForEncodings = 0; 316 | knownRegions = ( 317 | en, 318 | Base, 319 | ); 320 | mainGroup = FCEA068D1824966E004FDEE6; 321 | productRefGroup = FCEA06971824966E004FDEE6 /* Products */; 322 | projectDirPath = ""; 323 | projectRoot = ""; 324 | targets = ( 325 | FCEA06951824966E004FDEE6 /* iTunes Table Header */, 326 | FCEA06B61824966E004FDEE6 /* iTunes Table HeaderTests */, 327 | ); 328 | }; 329 | /* End PBXProject section */ 330 | 331 | /* Begin PBXResourcesBuildPhase section */ 332 | FCEA06941824966E004FDEE6 /* Resources */ = { 333 | isa = PBXResourcesBuildPhase; 334 | buildActionMask = 2147483647; 335 | files = ( 336 | FCA119161A07700E00791D17 /* bootstrap.min.js in Resources */, 337 | FC575EC51A09B33B003D03DC /* fullpie-index.js in Resources */, 338 | FCA119171A07700E00791D17 /* jquery-1.7.1.min.js in Resources */, 339 | FC54F39A1997304400609BB3 /* bootstrap.min.css in Resources */, 340 | FC575EC41A09B33B003D03DC /* fullpie-index.html in Resources */, 341 | FCA119191A0771C300791D17 /* jquery-1.7.1.min.js in Resources */, 342 | FCEA06A41824966E004FDEE6 /* InfoPlist.strings in Resources */, 343 | FCA119121A076E2C00791D17 /* pie-index.js in Resources */, 344 | FC54F39C1997304400609BB3 /* index.html in Resources */, 345 | FCA119141A076E2C00791D17 /* pie-style.css in Resources */, 346 | FCEA06B21824966E004FDEE6 /* Images.xcassets in Resources */, 347 | FCEA06AA1824966E004FDEE6 /* Credits.rtf in Resources */, 348 | FCEA06B01824966E004FDEE6 /* MainMenu.xib in Resources */, 349 | FCA119131A076E2C00791D17 /* pie-normalize.css in Resources */, 350 | FCA119111A076E2C00791D17 /* pie-index.html in Resources */, 351 | FC575EC61A09B33B003D03DC /* fullpie-style.css in Resources */, 352 | ); 353 | runOnlyForDeploymentPostprocessing = 0; 354 | }; 355 | FCEA06B51824966E004FDEE6 /* Resources */ = { 356 | isa = PBXResourcesBuildPhase; 357 | buildActionMask = 2147483647; 358 | files = ( 359 | FCEA06C21824966E004FDEE6 /* InfoPlist.strings in Resources */, 360 | ); 361 | runOnlyForDeploymentPostprocessing = 0; 362 | }; 363 | /* End PBXResourcesBuildPhase section */ 364 | 365 | /* Begin PBXSourcesBuildPhase section */ 366 | FCEA06921824966E004FDEE6 /* Sources */ = { 367 | isa = PBXSourcesBuildPhase; 368 | buildActionMask = 2147483647; 369 | files = ( 370 | FCEA06AD1824966E004FDEE6 /* AppDelegate.m in Sources */, 371 | FCEA06D51824ABF2004FDEE6 /* iArrayController.m in Sources */, 372 | FC8AF61F184BF6E5000968FF /* GraphController.m in Sources */, 373 | FCEA06A61824966E004FDEE6 /* main.m in Sources */, 374 | FCEA06D21824A114004FDEE6 /* iTableStyle.m in Sources */, 375 | FCEA06CF1824996B004FDEE6 /* iHeaderStyle.m in Sources */, 376 | ); 377 | runOnlyForDeploymentPostprocessing = 0; 378 | }; 379 | FCEA06B31824966E004FDEE6 /* Sources */ = { 380 | isa = PBXSourcesBuildPhase; 381 | buildActionMask = 2147483647; 382 | files = ( 383 | FCEA06C41824966E004FDEE6 /* iTunes_Table_HeaderTests.m in Sources */, 384 | ); 385 | runOnlyForDeploymentPostprocessing = 0; 386 | }; 387 | /* End PBXSourcesBuildPhase section */ 388 | 389 | /* Begin PBXTargetDependency section */ 390 | FCEA06BC1824966E004FDEE6 /* PBXTargetDependency */ = { 391 | isa = PBXTargetDependency; 392 | target = FCEA06951824966E004FDEE6 /* iTunes Table Header */; 393 | targetProxy = FCEA06BB1824966E004FDEE6 /* PBXContainerItemProxy */; 394 | }; 395 | /* End PBXTargetDependency section */ 396 | 397 | /* Begin PBXVariantGroup section */ 398 | FCEA06A21824966E004FDEE6 /* InfoPlist.strings */ = { 399 | isa = PBXVariantGroup; 400 | children = ( 401 | FCEA06A31824966E004FDEE6 /* en */, 402 | ); 403 | name = InfoPlist.strings; 404 | sourceTree = ""; 405 | }; 406 | FCEA06A81824966E004FDEE6 /* Credits.rtf */ = { 407 | isa = PBXVariantGroup; 408 | children = ( 409 | FCEA06A91824966E004FDEE6 /* en */, 410 | FC7D9D73182B44AD003D072C /* Base */, 411 | ); 412 | name = Credits.rtf; 413 | sourceTree = ""; 414 | }; 415 | FCEA06AE1824966E004FDEE6 /* MainMenu.xib */ = { 416 | isa = PBXVariantGroup; 417 | children = ( 418 | FCEA06AF1824966E004FDEE6 /* Base */, 419 | ); 420 | name = MainMenu.xib; 421 | sourceTree = ""; 422 | }; 423 | FCEA06C01824966E004FDEE6 /* InfoPlist.strings */ = { 424 | isa = PBXVariantGroup; 425 | children = ( 426 | FCEA06C11824966E004FDEE6 /* en */, 427 | ); 428 | name = InfoPlist.strings; 429 | sourceTree = ""; 430 | }; 431 | /* End PBXVariantGroup section */ 432 | 433 | /* Begin XCBuildConfiguration section */ 434 | FCEA06C51824966E004FDEE6 /* Debug */ = { 435 | isa = XCBuildConfiguration; 436 | buildSettings = { 437 | ALWAYS_SEARCH_USER_PATHS = NO; 438 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 439 | CLANG_CXX_LIBRARY = "libc++"; 440 | CLANG_ENABLE_OBJC_ARC = YES; 441 | CLANG_WARN_BOOL_CONVERSION = YES; 442 | CLANG_WARN_CONSTANT_CONVERSION = YES; 443 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 444 | CLANG_WARN_EMPTY_BODY = YES; 445 | CLANG_WARN_ENUM_CONVERSION = YES; 446 | CLANG_WARN_INT_CONVERSION = YES; 447 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 448 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 449 | COPY_PHASE_STRIP = NO; 450 | GCC_C_LANGUAGE_STANDARD = gnu99; 451 | GCC_DYNAMIC_NO_PIC = NO; 452 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 453 | GCC_OPTIMIZATION_LEVEL = 0; 454 | GCC_PREPROCESSOR_DEFINITIONS = ( 455 | "DEBUG=1", 456 | "$(inherited)", 457 | ); 458 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 459 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 460 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 461 | GCC_WARN_UNDECLARED_SELECTOR = YES; 462 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 463 | GCC_WARN_UNUSED_FUNCTION = YES; 464 | GCC_WARN_UNUSED_VARIABLE = YES; 465 | MACOSX_DEPLOYMENT_TARGET = 10.9; 466 | ONLY_ACTIVE_ARCH = YES; 467 | SDKROOT = macosx; 468 | }; 469 | name = Debug; 470 | }; 471 | FCEA06C61824966E004FDEE6 /* Release */ = { 472 | isa = XCBuildConfiguration; 473 | buildSettings = { 474 | ALWAYS_SEARCH_USER_PATHS = NO; 475 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 476 | CLANG_CXX_LIBRARY = "libc++"; 477 | CLANG_ENABLE_OBJC_ARC = YES; 478 | CLANG_WARN_BOOL_CONVERSION = YES; 479 | CLANG_WARN_CONSTANT_CONVERSION = YES; 480 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 481 | CLANG_WARN_EMPTY_BODY = YES; 482 | CLANG_WARN_ENUM_CONVERSION = YES; 483 | CLANG_WARN_INT_CONVERSION = YES; 484 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 485 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 486 | COPY_PHASE_STRIP = YES; 487 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 488 | ENABLE_NS_ASSERTIONS = NO; 489 | GCC_C_LANGUAGE_STANDARD = gnu99; 490 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 491 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 492 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 493 | GCC_WARN_UNDECLARED_SELECTOR = YES; 494 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 495 | GCC_WARN_UNUSED_FUNCTION = YES; 496 | GCC_WARN_UNUSED_VARIABLE = YES; 497 | MACOSX_DEPLOYMENT_TARGET = 10.9; 498 | SDKROOT = macosx; 499 | }; 500 | name = Release; 501 | }; 502 | FCEA06C81824966E004FDEE6 /* Debug */ = { 503 | isa = XCBuildConfiguration; 504 | buildSettings = { 505 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 506 | CLANG_ANALYZER_OBJC_UNUSED_IVARS = NO; 507 | CLANG_ENABLE_OBJC_ARC = NO; 508 | CODE_SIGN_IDENTITY = "-"; 509 | COMBINE_HIDPI_IMAGES = YES; 510 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 511 | GCC_PREFIX_HEADER = "iTunes Table Header/iTunes Table Header-Prefix.pch"; 512 | GCC_WARN_UNUSED_FUNCTION = NO; 513 | GCC_WARN_UNUSED_VALUE = NO; 514 | GCC_WARN_UNUSED_VARIABLE = NO; 515 | INFOPLIST_FILE = "iTunes Table Header/iTunes Table Header-Info.plist"; 516 | PRODUCT_NAME = "$(TARGET_NAME)"; 517 | WRAPPER_EXTENSION = app; 518 | }; 519 | name = Debug; 520 | }; 521 | FCEA06C91824966E004FDEE6 /* Release */ = { 522 | isa = XCBuildConfiguration; 523 | buildSettings = { 524 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 525 | CLANG_ANALYZER_OBJC_UNUSED_IVARS = NO; 526 | CLANG_ENABLE_OBJC_ARC = NO; 527 | CODE_SIGN_IDENTITY = "-"; 528 | COMBINE_HIDPI_IMAGES = YES; 529 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 530 | GCC_PREFIX_HEADER = "iTunes Table Header/iTunes Table Header-Prefix.pch"; 531 | GCC_WARN_UNUSED_FUNCTION = NO; 532 | GCC_WARN_UNUSED_VALUE = NO; 533 | GCC_WARN_UNUSED_VARIABLE = NO; 534 | INFOPLIST_FILE = "iTunes Table Header/iTunes Table Header-Info.plist"; 535 | PRODUCT_NAME = "$(TARGET_NAME)"; 536 | WRAPPER_EXTENSION = app; 537 | }; 538 | name = Release; 539 | }; 540 | FCEA06CB1824966E004FDEE6 /* Debug */ = { 541 | isa = XCBuildConfiguration; 542 | buildSettings = { 543 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/iTunes Table Header.app/Contents/MacOS/iTunes Table Header"; 544 | COMBINE_HIDPI_IMAGES = YES; 545 | FRAMEWORK_SEARCH_PATHS = ( 546 | "$(DEVELOPER_FRAMEWORKS_DIR)", 547 | "$(inherited)", 548 | ); 549 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 550 | GCC_PREFIX_HEADER = "iTunes Table Header/iTunes Table Header-Prefix.pch"; 551 | GCC_PREPROCESSOR_DEFINITIONS = ( 552 | "DEBUG=1", 553 | "$(inherited)", 554 | ); 555 | INFOPLIST_FILE = "iTunes Table HeaderTests/iTunes Table HeaderTests-Info.plist"; 556 | PRODUCT_NAME = "$(TARGET_NAME)"; 557 | TEST_HOST = "$(BUNDLE_LOADER)"; 558 | WRAPPER_EXTENSION = xctest; 559 | }; 560 | name = Debug; 561 | }; 562 | FCEA06CC1824966E004FDEE6 /* Release */ = { 563 | isa = XCBuildConfiguration; 564 | buildSettings = { 565 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/iTunes Table Header.app/Contents/MacOS/iTunes Table Header"; 566 | COMBINE_HIDPI_IMAGES = YES; 567 | FRAMEWORK_SEARCH_PATHS = ( 568 | "$(DEVELOPER_FRAMEWORKS_DIR)", 569 | "$(inherited)", 570 | ); 571 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 572 | GCC_PREFIX_HEADER = "iTunes Table Header/iTunes Table Header-Prefix.pch"; 573 | INFOPLIST_FILE = "iTunes Table HeaderTests/iTunes Table HeaderTests-Info.plist"; 574 | PRODUCT_NAME = "$(TARGET_NAME)"; 575 | TEST_HOST = "$(BUNDLE_LOADER)"; 576 | WRAPPER_EXTENSION = xctest; 577 | }; 578 | name = Release; 579 | }; 580 | /* End XCBuildConfiguration section */ 581 | 582 | /* Begin XCConfigurationList section */ 583 | FCEA06911824966E004FDEE6 /* Build configuration list for PBXProject "iTunes Table Header" */ = { 584 | isa = XCConfigurationList; 585 | buildConfigurations = ( 586 | FCEA06C51824966E004FDEE6 /* Debug */, 587 | FCEA06C61824966E004FDEE6 /* Release */, 588 | ); 589 | defaultConfigurationIsVisible = 0; 590 | defaultConfigurationName = Release; 591 | }; 592 | FCEA06C71824966E004FDEE6 /* Build configuration list for PBXNativeTarget "iTunes Table Header" */ = { 593 | isa = XCConfigurationList; 594 | buildConfigurations = ( 595 | FCEA06C81824966E004FDEE6 /* Debug */, 596 | FCEA06C91824966E004FDEE6 /* Release */, 597 | ); 598 | defaultConfigurationIsVisible = 0; 599 | defaultConfigurationName = Release; 600 | }; 601 | FCEA06CA1824966E004FDEE6 /* Build configuration list for PBXNativeTarget "iTunes Table HeaderTests" */ = { 602 | isa = XCConfigurationList; 603 | buildConfigurations = ( 604 | FCEA06CB1824966E004FDEE6 /* Debug */, 605 | FCEA06CC1824966E004FDEE6 /* Release */, 606 | ); 607 | defaultConfigurationIsVisible = 0; 608 | defaultConfigurationName = Release; 609 | }; 610 | /* End XCConfigurationList section */ 611 | }; 612 | rootObject = FCEA068E1824966E004FDEE6 /* Project object */; 613 | } 614 | -------------------------------------------------------------------------------- /iTunes Table Header.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /iTunes Table Header.xcodeproj/project.xcworkspace/xcshareddata/iTunes Table Header.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 3D1C57F9-044C-435A-AAAB-F86904E16837 9 | IDESourceControlProjectName 10 | iTunes Table Header 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 68E47E6B128B9CD2837FE1B2A762888C2708B131 14 | https://github.com/jonbrown21/Horizontal-Graph-Controller.git 15 | 16 | IDESourceControlProjectPath 17 | iTunes Table Header.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 68E47E6B128B9CD2837FE1B2A762888C2708B131 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/jonbrown21/Horizontal-Graph-Controller.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 68E47E6B128B9CD2837FE1B2A762888C2708B131 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 68E47E6B128B9CD2837FE1B2A762888C2708B131 36 | IDESourceControlWCCName 37 | Horizontal-Graph-Controller 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /iTunes Table Header.xcodeproj/project.xcworkspace/xcuserdata/jon.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonbrown21/Horizontal-Graph-Controller/812e4e18a7e192f3329ca480a052653cb20607fe/iTunes Table Header.xcodeproj/project.xcworkspace/xcuserdata/jon.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /iTunes Table Header.xcodeproj/xcuserdata/jon.xcuserdatad/xcschemes/iTunes Table Header.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /iTunes Table Header.xcodeproj/xcuserdata/jon.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | iTunes Table Header.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | FCEA06951824966E004FDEE6 16 | 17 | primary 18 | 19 | 20 | FCEA06B61824966E004FDEE6 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /iTunes Table Header/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // iTunes Table Header 4 | // 5 | // Created by Jon Brown on 11/1/13. 6 | // Copyright (c) 2013 Jon Brown Designs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : NSObject 12 | { 13 | IBOutlet NSTableView *tableView; 14 | IBOutlet id webView; 15 | IBOutlet id typeField; 16 | IBOutlet id myView; 17 | } 18 | 19 | 20 | @property (assign) IBOutlet NSWindow *window; 21 | - (IBAction)changeOperation:(id)sender; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /iTunes Table Header/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // iTunes Table Header 4 | // 5 | // Created by Jon Brown on 11/1/13. 6 | // Copyright (c) 2013 Jon Brown Designs. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "iHeaderStyle.h" 11 | #import 12 | 13 | @implementation AppDelegate 14 | 15 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 16 | { 17 | // Insert code here to initialize your application 18 | } 19 | 20 | -(void)awakeFromNib 21 | { 22 | /* set preference defaults */ 23 | [[NSUserDefaults standardUserDefaults] registerDefaults: 24 | [NSDictionary dictionaryWithObject: [NSNumber numberWithBool: YES] 25 | forKey: @"NSDisabledCharacterPaletteMenuItem"]]; 26 | 27 | NSArray *columns = [tableView tableColumns]; 28 | NSEnumerator *cols = [columns objectEnumerator]; 29 | NSTableColumn *col = nil; 30 | 31 | iHeaderStyle *iHeaderCell; 32 | 33 | while (col = [cols nextObject]) { 34 | iHeaderCell = [[iHeaderStyle alloc] 35 | initTextCell:[[col headerCell] stringValue]]; 36 | [col setHeaderCell:iHeaderCell]; 37 | [iHeaderCell release]; 38 | } 39 | 40 | NSString *path1 = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"]; 41 | NSString *html = [NSString stringWithContentsOfFile:path1 encoding:NSUTF8StringEncoding error:nil]; 42 | [[[webView mainFrame] frameView] setAllowsScrolling:NO]; 43 | [[webView mainFrame] loadHTMLString:html baseURL:[[NSBundle mainBundle] resourceURL]]; 44 | [webView setDrawsBackground:NO]; 45 | 46 | 47 | NSView *view = webView; 48 | [view setWantsLayer:YES]; 49 | [myView addSubview:view]; 50 | 51 | NSRect aFrame = [_window frame]; 52 | aFrame.origin.y += (aFrame.size.height - 150) ; 53 | aFrame.size.height = 340 ; //original size is 400 54 | [_window setFrame:aFrame display:YES animate:YES]; 55 | 56 | 57 | } 58 | 59 | - (IBAction)changeOperation:(id)sender { 60 | 61 | NSString *path1 = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"]; 62 | NSString *html = [NSString stringWithContentsOfFile:path1 encoding:NSUTF8StringEncoding error:nil]; 63 | NSURL *url = [NSURL fileURLWithPath:path1]; 64 | 65 | NSString *path2 = [[NSBundle mainBundle] pathForResource:@"pie-index" ofType:@"html"]; 66 | NSString *html2 = [NSString stringWithContentsOfFile:path2 encoding:NSUTF8StringEncoding error:nil]; 67 | NSURL *url2 = [NSURL fileURLWithPath:path2]; 68 | 69 | NSString *path3 = [[NSBundle mainBundle] pathForResource:@"fullpie-index" ofType:@"html"]; 70 | NSString *html3 = [NSString stringWithContentsOfFile:path3 encoding:NSUTF8StringEncoding error:nil]; 71 | NSURL *url3 = [NSURL fileURLWithPath:path3]; 72 | 73 | NSRect aFrame = [_window frame]; 74 | 75 | long operation; 76 | 77 | operation = [typeField selectedTag]; 78 | 79 | switch (operation) { 80 | case 0: 81 | 82 | [[webView mainFrame] loadRequest:[NSURLRequest requestWithURL:url]]; 83 | 84 | 85 | aFrame.origin.y += (aFrame.size.height - 500) ; 86 | aFrame.size.height = 340 ; //original size is 400 87 | [_window setFrame:aFrame display:YES animate:YES]; 88 | 89 | break; 90 | case 1: 91 | 92 | [[[webView mainFrame] frameView] setAllowsScrolling:NO]; 93 | [[webView mainFrame] loadHTMLString:html2 baseURL:[[NSBundle mainBundle] resourceURL]]; 94 | [[webView mainFrame] loadRequest:[NSURLRequest requestWithURL:url2]]; 95 | [webView setDrawsBackground:NO]; 96 | NSLog(@"Donut"); 97 | 98 | aFrame.origin.y += (aFrame.size.height - 300) ; 99 | aFrame.size.height = 490 ; //original size is 400 100 | [_window setFrame:aFrame display:YES animate:YES]; 101 | 102 | break; 103 | 104 | case 2: 105 | 106 | [[[webView mainFrame] frameView] setAllowsScrolling:NO]; 107 | [[webView mainFrame] loadHTMLString:html3 baseURL:[[NSBundle mainBundle] resourceURL]]; 108 | [[webView mainFrame] loadRequest:[NSURLRequest requestWithURL:url3]]; 109 | [webView setDrawsBackground:NO]; 110 | NSLog(@"Full Pie"); 111 | 112 | aFrame.origin.y += (aFrame.size.height - 300) ; 113 | aFrame.size.height = 495 ; //original size is 400 114 | [_window setFrame:aFrame display:YES animate:YES]; 115 | 116 | break; 117 | } 118 | 119 | } 120 | 121 | 122 | 123 | @end 124 | -------------------------------------------------------------------------------- /iTunes Table Header/Base.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1265 2 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \vieww9600\viewh8400\viewkind0 5 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc 6 | 7 | \f0\b\fs24 \cf0 Development 8 | \b0 \ 9 | Jon Brown\ 10 | \ 11 | 12 | \b Interface Design 13 | \b0 \ 14 | Jon Brown\ 15 | \ 16 | 17 | \b With special thanks to 18 | \b0 \ 19 | Core code inspired by Matt Gemmell\ 20 | \ 21 | 22 | \b Copyright\ 23 | 24 | \b0 MIT License} -------------------------------------------------------------------------------- /iTunes Table Header/Base.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | Default 524 | 525 | 526 | 527 | 528 | 529 | 530 | Left to Right 531 | 532 | 533 | 534 | 535 | 536 | 537 | Right to Left 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | Default 549 | 550 | 551 | 552 | 553 | 554 | 555 | Left to Right 556 | 557 | 558 | 559 | 560 | 561 | 562 | Right to Left 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 764 | 767 | 768 | 769 | 770 | 771 | 772 | 783 | 794 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 | 892 | 893 | 894 | 895 | 896 | 897 | 898 | 899 | 900 | 901 | 902 | 903 | 904 | 905 | 906 | 907 | 908 | 909 | 910 | 911 | 912 | 913 | 914 | 915 | 916 | 917 | 918 | 919 | 920 | 921 | 922 | 923 | 924 | 925 | 926 | 927 | 928 | 929 | 930 | 931 | 932 | 933 | 934 | 935 | 936 | 937 | 938 | 939 | 940 | 941 | 942 | 943 | 944 | 945 | 946 | 947 | 948 | 949 | 950 | -------------------------------------------------------------------------------- /iTunes Table Header/GraphController.h: -------------------------------------------------------------------------------- 1 | // 2 | // GraphController.h 3 | // iTunes Table Header 4 | // 5 | // Created by Jon Brown on 12/1/13. 6 | // Copyright (c) 2013 Jon Brown Designs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface GraphController : WebView 12 | { 13 | IBOutlet id iArrayController; 14 | IBOutlet NSTextField *textField; 15 | IBOutlet NSTextField *textField2; 16 | IBOutlet NSTextField *textField3; 17 | IBOutlet NSTextField *textField4; 18 | IBOutlet NSTextField *textField5; 19 | IBOutlet NSTextField *textField6; 20 | IBOutlet NSTableView *tableView; 21 | } 22 | - (IBAction)refreshData:(id)sender; 23 | 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /iTunes Table Header/GraphController.m: -------------------------------------------------------------------------------- 1 | // 2 | // GraphController.m 3 | // iTunes Table Header 4 | // 5 | // Created by Jon Brown on 12/1/13. 6 | // Copyright (c) 2013 Jon Brown Designs. All rights reserved. 7 | // 8 | 9 | #import "GraphController.h" 10 | #import 11 | 12 | @implementation GraphController 13 | 14 | -(void)drawGraphFromSelectedList 15 | { 16 | //Convert the item1 into an Integer 17 | 18 | NSString *item1 = [textField stringValue]; 19 | 20 | //Convert the item2 into an Integer 21 | 22 | NSString *item2 = [textField2 stringValue]; 23 | 24 | //Convert the item3 into an Integer 25 | 26 | NSString *item3 = [textField3 stringValue]; 27 | NSString *item4 = [textField4 stringValue]; 28 | NSString *item5 = [textField5 stringValue]; 29 | NSString *item6 = [textField6 stringValue]; 30 | 31 | //pass that to webview with javascript Bar Graph 32 | NSString *javascriptString = [NSString stringWithFormat:@"myFunction('%@','%@','%@')", item1, item2, item3]; 33 | 34 | //pass that to webview with javascript Donut Graph 35 | NSString *javascriptString2 = [NSString stringWithFormat:@"myFunction2(%@,%@,%@,'%@','%@','%@')", item1, item2, item3, item4, item5, item6]; 36 | 37 | //pass that to webview with javascript Donut Graph 38 | NSString *javascriptString3 = [NSString stringWithFormat:@"myFunction3(%@,%@,%@,'%@','%@','%@')", item1, item2, item3, item4, item5, item6]; 39 | 40 | NSLog(@"%@", javascriptString3); 41 | 42 | //pass that to webview with javascript Bar Graph 43 | [self stringByEvaluatingJavaScriptFromString:javascriptString]; 44 | 45 | //pass that to webview with javascript Donut Graph 46 | [self stringByEvaluatingJavaScriptFromString:javascriptString2]; 47 | 48 | //pass that to webview with javascript Donut Graph 49 | [self stringByEvaluatingJavaScriptFromString:javascriptString3]; 50 | 51 | 52 | } 53 | 54 | - (void)drawRect:(NSRect)dirtyRect 55 | { 56 | 57 | [super drawRect:dirtyRect]; 58 | 59 | // Force graph to reload / redraw on window size and on WebView load. 60 | 61 | [self performSelector:@selector(refreshData:) withObject:nil afterDelay:0.25]; 62 | 63 | } 64 | 65 | - (void)awakeFromNib 66 | { 67 | 68 | [iArrayController addObserver:self forKeyPath:@"arrangedObjects" 69 | options: NSKeyValueObservingOptionNew context:NULL]; 70 | 71 | } 72 | 73 | - (IBAction)refreshData:(id)sender { 74 | 75 | [tableView reloadData]; 76 | [self drawGraphFromSelectedList]; 77 | 78 | 79 | } 80 | 81 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object 82 | change:(NSDictionary *)change context:(void *)context 83 | { 84 | 85 | if ([keyPath isEqual:@"arrangedObjects"]) 86 | { 87 | [self setNeedsDisplay: YES]; 88 | } 89 | } 90 | 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /iTunes Table Header/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /iTunes Table Header/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1265 2 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \vieww9600\viewh8400\viewkind0 5 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc 6 | 7 | \f0\b\fs24 \cf0 Development 8 | \b0 \ 9 | Jon Brown\ 10 | \ 11 | 12 | \b Interface Design 13 | \b0 \ 14 | Jon Brown\ 15 | \ 16 | 17 | \b With special thanks to 18 | \b0 \ 19 | Core code inspired by Matt Gemmell\ 20 | \ 21 | 22 | \b Copyright\ 23 | 24 | \b0 MIT License} -------------------------------------------------------------------------------- /iTunes Table Header/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /iTunes Table Header/iArrayController.h: -------------------------------------------------------------------------------- 1 | // 2 | // iArrayController.h 3 | // iTunes Table Header 4 | // 5 | // Created by Jon Brown on 11/1/13. 6 | // Copyright (c) 2013 Jon Brown Designs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface iArrayController : NSArrayController 12 | { 13 | IBOutlet NSTextField *textField; 14 | IBOutlet NSTextField *textField2; 15 | IBOutlet NSTextField *textField3; 16 | } 17 | 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /iTunes Table Header/iArrayController.m: -------------------------------------------------------------------------------- 1 | // 2 | // iArrayController.m 3 | // iTunes Table Header 4 | // 5 | // Created by Jon Brown on 11/1/13. 6 | // Copyright (c) 2013 Jon Brown Designs. All rights reserved. 7 | // 8 | 9 | #import "iArrayController.h" 10 | 11 | @implementation iArrayController 12 | 13 | -(void)awakeFromNib 14 | { 15 | //Sorting at startup 16 | NSSortDescriptor* SortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"artist" 17 | ascending:YES selector:@selector(compare:)] autorelease]; 18 | [self setSortDescriptors:[NSArray arrayWithObject:SortDescriptor]]; 19 | 20 | //need to initialize the array 21 | [super awakeFromNib]; 22 | 23 | //bind text colums to text fields. 24 | [textField bind: @"value" toObject: self 25 | withKeyPath:@"arrangedObjects.@sum.rating" options:nil]; 26 | 27 | [textField2 bind: @"value" toObject: self 28 | withKeyPath:@"arrangedObjects.@sum.time" options:nil]; 29 | 30 | [textField3 bind: @"value" toObject: self 31 | withKeyPath:@"arrangedObjects.@sum.track" options:nil]; 32 | 33 | } 34 | 35 | 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /iTunes Table Header/iHeaderStyle.h: -------------------------------------------------------------------------------- 1 | // 2 | // iHeaderStyle.h 3 | // iTunes Table Header 4 | // 5 | // Created by Jon Brown on 11/1/13. 6 | // Copyright (c) 2013 Jon Brown Designs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface iHeaderStyle : NSTableHeaderCell { 12 | NSMutableDictionary *attrs; 13 | } 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /iTunes Table Header/iHeaderStyle.m: -------------------------------------------------------------------------------- 1 | // 2 | // iHeaderStyle.m 3 | // iTunes Table Header 4 | // 5 | // Created by Jon Brown on 11/1/13. 6 | // Copyright (c) 2013 Jon Brown Designs. All rights reserved. 7 | // 8 | 9 | #import "iHeaderStyle.h" 10 | 11 | @implementation iHeaderStyle 12 | 13 | - (id)initTextCell:(NSString *)text 14 | { 15 | if (self = [super initTextCell:text]) { 16 | 17 | if (text == nil || [text isEqualToString:@""]) { 18 | [self setTitle:@"Title"]; 19 | } 20 | 21 | attrs = [[NSMutableDictionary dictionaryWithDictionary: 22 | [[self attributedStringValue] 23 | attributesAtIndex:0 24 | effectiveRange:NULL]] 25 | mutableCopy]; 26 | return self; 27 | } 28 | return nil; 29 | } 30 | 31 | - (void)drawWithFrame:(CGRect)cellFrame 32 | highlighted:(BOOL)isHighlighted 33 | inView:(NSView *)view 34 | { 35 | 36 | CGRect fillRect, borderRect; 37 | CGRectDivide(cellFrame, &borderRect, &fillRect, 1.0, CGRectMaxYEdge); 38 | 39 | NSGradient *gradient = [[NSGradient alloc] 40 | initWithStartingColor:[NSColor whiteColor] 41 | endingColor:[NSColor colorWithDeviceWhite:0.9 alpha:1.0]]; 42 | [gradient drawInRect:fillRect angle:90.0]; 43 | [gradient release]; 44 | 45 | 46 | if (isHighlighted) { 47 | [[NSColor colorWithDeviceWhite:0.0 alpha:0.1] set]; 48 | NSRectFillUsingOperation(fillRect, NSCompositeSourceOver); 49 | } 50 | 51 | [[NSColor colorWithDeviceWhite:0.8 alpha:1.0] set]; 52 | NSRectFill(borderRect); 53 | 54 | 55 | [self drawInteriorWithFrame:CGRectInset(fillRect, 0.0, 1.0) inView:view]; 56 | 57 | 58 | // Draw the column divider. 59 | [[NSColor lightGrayColor] set]; 60 | NSRect _dividerRect = NSMakeRect(cellFrame.origin.x + cellFrame.size.width -1, 0, 1,cellFrame.size.height); 61 | NSRectFill(_dividerRect); 62 | 63 | 64 | } 65 | 66 | 67 | - (void)drawWithFrame:(CGRect)cellFrame inView:(NSView *)view 68 | { 69 | [self drawWithFrame:cellFrame highlighted:NO inView:view]; 70 | } 71 | 72 | - (void)highlight:(BOOL)isHighlighted 73 | withFrame:(NSRect)cellFrame 74 | inView:(NSView *)view 75 | { 76 | [self drawWithFrame:cellFrame highlighted:isHighlighted inView:view]; 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /iTunes Table Header/iTableStyle.h: -------------------------------------------------------------------------------- 1 | // 2 | // iTableStyle.h 3 | // iTunes Table Header 4 | // 5 | // Created by Jon Brown on 11/1/13. 6 | // Copyright (c) 2013 Jon Brown Designs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface iTableStyle : NSTableView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /iTunes Table Header/iTableStyle.m: -------------------------------------------------------------------------------- 1 | // 2 | // iTableStyle.m 3 | // iTunes Table Header 4 | // 5 | // Created by Jon Brown on 11/1/13. 6 | // Copyright (c) 2013 Jon Brown Designs. All rights reserved. 7 | // 8 | 9 | #import "iTableStyle.h" 10 | 11 | @implementation iTableStyle 12 | 13 | - (void)highlightSelectionInClipRect:(NSRect)theClipRect 14 | { 15 | 16 | // this method is asking us to draw the hightlights for 17 | // all of the selected rows that are visible inside theClipRect 18 | 19 | // 1. get the range of row indexes that are currently visible 20 | // 2. get a list of selected rows 21 | // 3. iterate over the visible rows and if their index is selected 22 | // 4. draw our custom highlight in the rect of that row. 23 | 24 | NSRange aVisibleRowIndexes = [self rowsInRect:theClipRect]; 25 | NSIndexSet* aSelectedRowIndexes = [self selectedRowIndexes]; 26 | long aRow = aVisibleRowIndexes.location; 27 | long anEndRow = aRow + aVisibleRowIndexes.length; 28 | NSGradient* gradient; 29 | NSColor* pathColor; 30 | 31 | // if the view is focused, use highlight color, otherwise use the out-of-focus highlight color 32 | if (self == [[self window] firstResponder] && [[self window] isMainWindow] && [[self window] isKeyWindow]) 33 | { 34 | 35 | gradient = [[[NSGradient alloc] initWithColorsAndLocations: 36 | [NSColor colorWithDeviceRed:(float)128/255 green:(float)157/255 blue:(float)194/255 alpha:1.0], 0.0, 37 | [NSColor colorWithDeviceRed:(float)128/255 green:(float)157/255 blue:(float)194/255 alpha:1.0], 1.0, nil] retain]; 38 | 39 | pathColor = [[NSColor colorWithDeviceRed:(float)128/255 green:(float)157/255 blue:(float)194/255 alpha:1.0] retain]; 40 | 41 | } 42 | else 43 | { 44 | 45 | gradient = [[[NSGradient alloc] initWithColorsAndLocations: 46 | [NSColor colorWithDeviceRed:(float)186/255 green:(float)192/255 blue:(float)203/255 alpha:1.0], 0.0, 47 | [NSColor colorWithDeviceRed:(float)186/255 green:(float)192/255 blue:(float)203/255 alpha:1.0], 1.0, nil] retain]; //160 80 48 | 49 | pathColor = [[NSColor colorWithDeviceRed:(float)186/255 green:(float)192/255 blue:(float)203/255 alpha:1.0] retain]; 50 | 51 | } 52 | 53 | // draw highlight for the visible, selected rows 54 | 55 | for (aRow; aRow < anEndRow; aRow++) { 56 | 57 | if([aSelectedRowIndexes containsIndex:aRow]) 58 | { 59 | NSRect aRowRect = NSInsetRect([self rectOfRow:aRow], 0, 0); //first is horizontal, second is vertical 60 | NSBezierPath * path = [NSBezierPath bezierPathWithRect:aRowRect]; //6.0 61 | 62 | [gradient drawInBezierPath:path angle:90]; 63 | 64 | } 65 | } 66 | 67 | } 68 | 69 | 70 | 71 | 72 | - (id)_highlightColorForCell:(NSCell *)cell 73 | { 74 | // we need to override this to return nil 75 | // or we'll see the default selection rectangle when the app is running 76 | // in any OS before leopard 77 | 78 | // you can also return a color if you simply want to change the table's default selection color 79 | return nil; 80 | } 81 | 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /iTunes Table Header/iTunes Table Header-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.jonbrown.org.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSHumanReadableCopyright 28 | Copyright © 2013 Jon Brown Designs. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /iTunes Table Header/iTunes Table Header-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /iTunes Table Header/iTunes Table Header.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /iTunes Table Header/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // iTunes Table Header 4 | // 5 | // Created by Jon Brown on 11/1/13. 6 | // Copyright (c) 2013 Jon Brown Designs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) 12 | { 13 | return NSApplicationMain(argc, argv); 14 | } 15 | -------------------------------------------------------------------------------- /iTunes Table HeaderTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /iTunes Table HeaderTests/iTunes Table HeaderTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.jonbrown.org.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /iTunes Table HeaderTests/iTunes_Table_HeaderTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // iTunes_Table_HeaderTests.m 3 | // iTunes Table HeaderTests 4 | // 5 | // Created by Jon Brown on 11/1/13. 6 | // Copyright (c) 2013 Jon Brown Designs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface iTunes_Table_HeaderTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation iTunes_Table_HeaderTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /screenshot/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonbrown21/Horizontal-Graph-Controller/812e4e18a7e192f3329ca480a052653cb20607fe/screenshot/2.png -------------------------------------------------------------------------------- /screenshot/HorizontalGraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonbrown21/Horizontal-Graph-Controller/812e4e18a7e192f3329ca480a052653cb20607fe/screenshot/HorizontalGraph.png -------------------------------------------------------------------------------- /screenshot/graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonbrown21/Horizontal-Graph-Controller/812e4e18a7e192f3329ca480a052653cb20607fe/screenshot/graph.png -------------------------------------------------------------------------------- /screenshot/iTunesWindow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonbrown21/Horizontal-Graph-Controller/812e4e18a7e192f3329ca480a052653cb20607fe/screenshot/iTunesWindow.png --------------------------------------------------------------------------------