при создании своих панелек нужно править раздел application, что в самом конце.
в общем, тут всё понятно - создаём дерево объектов с заданием отличных от дефолтных параметров, которое обновляется при ресайзе (ресурсов тратится не слишком много, зато разработка упрощается) и по необходимости скопом отображаем, не забыв подредактировать некоторые параметры. дети рисуются в порядке очереди поверх родителей. смотрите исходники объектов, чтобы узнать какие параметры они поддерживают. любой объект можно инициализироать без параметров либо другим объектом (все поля будут скопированы и известные объекту будут приведены к необходимому типу). дефолтные значения цветов лучше не изменять - они специально подобраны для отладки. выполнять make() вручную не требуется, кроме случаев прямого изменения параметров и последующей прямой работой с канвой.
- Код: Выделить всё
/* [ oop foobar2000 scripting v.5 ] */
/* license: free */
Object.prototype.toString= function () {
var str=[];
for (i in this) str.push ( i+':'+this[i] );
return '{'+str+'}';
}
/* [ foobar2000 API ]
global fb {
trace ( v ); // dump variable to console
ComponentPath; // full path to ./foobar/components/
TitleFormat ( tagz_str ); // returns titleformat object for a string (use Eval() to process to string)
PlaybackLength;
PlaybackTime;
IsPlaying;
volume;
PlayOrPause();
Prev();
Next();
}
global gdi {
Font ( -size, weight, italic, underline, family_name ); // returns a gdi font
Image ( path ); // returns a gdi image
}
canvas {
DrawLine ( x1, y1, x2, y2, thickness, color );
DrawRect ( x, y, width, height, thickness, color );
FillSolidRect (x, y, width, height, color );
FillGradRect ( x, y, width, height, gradient_angle, color1, color2 );
DrawString ( text, gdi_font, color, x, y, width, height, add_params );
DrawImage ( gdi_image, x, y, width, height, image_x, image_y, image_width, image_height);
}
window {
Width;
Height;
}
*/
/* [ EVENTS HANDLERS ] */
function on_paint(canvas) {
this.ww;
this.wh;
if ( window.Width!=this.ww || window.Height!=this.wh ) $.onResize && $.onResize();
this.ww= window.Width;
this.wh= window.Height;
$.canvas= canvas;
$.onPaint && $.onPaint();
}
function on_playback_starting(cmd, paused){
$.onPlay && $.onPlay();
}
function on_playback_new_track(track){
var t= {};
t.path= track.path;
t.subSong= track.SubSong;
t.fileSize= track.FileSize;
t.length= track.Length;
t.meta= {};
for ( var i=0; i<track.MetaCount; ++i ) {
var m= [];
for ( var j=0; j<track.MetaValueCount(i); ++j ) m.push( track.MetaValue ( i, j ) );
t.meta[ track.MetaName (i) ]= m;
}
t.info= {};
for ( var i=0; i<track.InfoCount; ++i ) t.info[ track.InfoName (i) ]= track.InfoValue (i);
$.track= t;
$.onNext && $.onNext();
}
function on_playback_stop(){
$.onStop && $.onStop();
}
function on_playback_seek(time){
$.playTime= time;
$.onSeek && $.onSeek();
}
function on_playback_pause(state){
window.Repaint();
}
function on_playback_edited(){
$.onPlaybackEdit && $.onPlaybackEdit();
}
function on_playback_dynamic_info() {
$.onDynamicInfo && $.onDynamicInfo();
}
function on_playback_dynamic_info_track() {
$.onDynamicTrack && $.onDynamicTrack();
}
function on_playback_time(time){
$.playTime= time;
$.onTick && $.onTick();
}
function on_volume_change(volume){
$.volume= volume;
$.onVolume && $.onVolume();
}
function on_mouse_lbtn_down(x,y){
$.mouseX= x;
$.mouseY= y;
$.mouseBtns|= 1;
$.onMouseDown && $.onMouseDown();
}
function on_mouse_lbtn_up(x,y){
$.mouseX= x;
$.mouseY= y;
$.mouseBtns&= ~1;
$.onMouseUp && $.onMouseUp();
}
function on_mouse_move(x,y){
$.mouseX= x;
$.mouseY= y;
$.onMouseMove && $.onMouseMove();
}
function on_mouse_wheel(delta){
$.wheelDelta= delta;
$.onWheel && $.onWheel (delta) || (fb.volume+= delta);
}
/* [ LOW LEVEL OBJECTS ] */
var Color= function (color) {
this.presets= {
red: { r:255, g:0, b:0 },
green: { r:0, g:255, b:0 },
blue: { r:0, g:0, b:255 },
white: { r:255, g:255, b:255 },
gray: { r:127, g:127, b:127 },
black: { r:0, g:0, b:0 }
};
if (color && typeof color == 'number') {
this.b= color & 0xFF;
this.g= color>>8 & 0xFF;
this.r= color>>16 & 0xFF;
this.a= color>>24 & 0xFF;
} else {
var preset= this.presets[color];
this.r= preset && preset.r || color && color.r || 0;
this.g= preset && preset.g || color && color.g || 0;
this.b= preset && preset.b || color && color.b || 0;
this.a= preset && preset.a || color && color.a || 0;
};
this.make= function () {
this.raw= (255-this.a)<<24
| this.r<<16
| this.g<<8
| this.b;
return this;
}; this.make();
}
var Font= function (font) {
for (i in font) this[i]= font[i];
this.size= this.size || 12;
this.weight= this.weight || 400;
this.italic= this.italic || 0;
this.undeline= this.underline || 0;
this.name= this.name || 'Arial';
this.make= function () {
this.raw= gdi.Font(-this.size, this.weight,this.italic, this.underline, this.name);
return this;
}; this.make();
return this;
}
var TextProp= function (prop) {
for (i in prop) this[i]= prop[i];
this.alignes= { start:0, middle:1, end:2 };
this.trimes= { no:0, char:1, word:2, elipsChar:3, elipsWord:4, elipsPath:5 };
this.alignH= this.alignH || 'middle';
this.alignV= this.alignV || 'middle';
this.trim= this.trim || 'no';
this.rtl= this.rtl || 0;
this.vertical= this.vertical || 0;
this.noFit= this.noFit || 0;
this.noCtrl= this.noCtrl || 0;
this.noFallback= this.noFallback || 0;
this.trailSpace= this.trailSpace || 0;
this.noWrap= this.noWrap || 0;
this.lineLimit= this.lineLimit || 0;
this.noClip= this.noClip || 0;
this.make= function () {
this.raw= this.alignes[this.alignH]<<28
| this.alignes[this.alignV]<<24
| this.trimes[this.trim]<<20
| this.noClip<<14
| this.lineLimit<<13
| this.noWrap<<12
| this.trailSpace<<11
| this.noFallback<<10
| this.noCtrl<<5
| this.noFit<<2
| this.vertical<<1
| this.rtl;
return this;
}; this.make();
return this;
}
/* [ HIGH LEVEL OBJECTS ] */
var Box= function (box) {
for (i in box) this[i]= box[i];
this.x= this.x || 0;
this.y= this.y || 0;
this.width= this.width || window.Width-this.x;
this.height= this.height || window.Height-this.y;
}
var FrameBox= function (box) {
for (i in box) this[i]= box[i];
this.box= new Box ( this.box );
this.color= new Color( 'color' in this ? this.color : 0xFF0000 );
this.thick= this.thick || 1;
this.render= function () {
$.canvas.DrawRect (
this.box.x, this.box.y, this.box.width-1, this.box.height-1,
this.thick, this.color.raw
);
for (i in this.childs) this.childs[i].render();
};
}
var GradBox= function (box) {
for (i in box) this[i]= box[i];
this.box= new Box ( this.box );
this.color1= new Color( 'color1' in this ? this.color1 : 0x66000000 );
this.color2= new Color( 'color2' in this ? this.color2 : 0x660000FF );
this.angel= this.angel || 0;
this.render= function () {
try {
$.canvas.FillGradRect (
this.box.x, this.box.y, this.box.width, this.box.height,
this.angel, this.color1.raw, this.color2.raw
);
} catch (e) {fb.trace(e.message);};
for (i in this.childs) this.childs[i].render();
};
}
var TextBox= function (box) {
for (i in box) this[i]= box[i];
this.box= new Box ( this.box );
this.color= new Color( 'color' in this ? this.color : 'green' );
this.font= new Font ( this.font );
this.textProp= new TextProp ( this.textProp );
this.text= this.text || '';
this.render= function () {
$.canvas.DrawString(
this.text, this.font.raw, this.color.raw,
this.box.x, this.box.y, this.box.width, this.box.height,
this.textProp.raw
)
for (i in this.childs) this.childs[i].render();
}
}
var Image= function ( image ) {
this.make= function () {
this.raw= gdi.Image ( this.path );
return this;
};
for (i in image) this[i]= image[i];
this.path= this.path || fb.ComponentPath+'..\\nocover.jpg';
this.make();
this.box= new Box ( this.box );
this.crop= new Box ( this.crop || { x:0, y:0, width:this.raw.Width, height:this.raw.Height } );
this.render= function () {
$.canvas.DrawImage (
this.raw,
this.box.x, this.box.y, this.box.width, this.box.height,
this.crop.x, this.crop.y, this.crop.width, this.crop.height
)
for (i in this.childs) this.childs[i].render();
}
}
/* [ APPLICATION ] */
var track_info= { /* version 1.1 */
onResize: function () {
var sliderWidth= 30;
var minRect= Math.min ( window.Width, window.Height);
var strong= new Font ({
weight: 800
});
this.childs= {
blur: new GradBox ({
angel: 90,
color2: 0x00DDEEFF,
color1: 0x00AABBCC,
childs: {}
}),
progress: new GradBox ({
angel: 90,
color1: 0x00DDEEFF,
color2: 0x00BBCCDD,
childs: {}
}),
tags: new TextBox ({
color: 'black',
textProp: new TextProp ({
alignH: 'end',
alignV: 'start'
}),
box: {
y: 5,
width: window.Width-5
},
childs: {}
}),
format: new TextBox ({
color: 'black',
font: strong,
text: ' \n\
codec: \n\
bitrate: \n\
samplerate: \n\
chanels: \n\
',
textProp: new TextProp ({
alignH: 'end',
alignV: 'end'
}),
box: {
width: 80,
height: window.Height+10
},
childs: {
data: new TextBox ({
color: 'black',
textProp: new TextProp ({
alignH: 'start',
alignV: 'end'
}),
box: {
x: 80,
height: window.Height+10
},
childs: {}
})
}
}),
addata: new TextBox ({
color: 'black',
font: strong,
text: ' \n\
mood: \n\
date: \n\
',
textProp: new TextProp ({
alignH: 'end',
alignV: 'end'
}),
box: {
width: window.Width-75,
height: window.Height+10
},
childs: {
data: new TextBox ({
color: 'black',
text: '123323',
textProp: new TextProp ({
alignH: 'start',
alignV: 'end'
}),
box: {
x: window.Width-75,
width: 75,
height: window.Height+10
},
childs: {}
})
}
}),
data: new TextBox ({
color: 'black',
childs: {}
}),
title: new TextBox ({
color: 'black',
font: strong,
childs: {}
}),
frame: new FrameBox ({
color: 'gray',
childs: {}
})
};
this.onTick();
this.onNext();
},
onPaint: function () {
for (i in this.childs) this.childs[i].render();
},
onTick: function () {
this.childs.progress.box.width= Math.ceil(fb.PlaybackTime*window.Width/fb.PlaybackLength);
window.Repaint();
},
onSeek: function() {
this.onTick();
},
onNext: function () {
this.childs.data.text= this.tagz(" \n\
[%artist%]$if($strcmp(%artist%,%album artist%),, | %album artist%) \n\
\n\
[{ %album% }] \n\
");
this.childs.title.text= this.tagz("%title%");
this.childs.tags.text= this.tagz("[%tags%]");
this.childs.format.childs.data.text= this.tagz(" \n\
%codec% \n\
%bitrate% kbps \n\
%samplerate% Hz \n\
%channels% \n\
");
this.childs.addata.childs.data.text= this.tagz(" \n\
%mood% \n\
%date% \n\
");
window.Repaint();
},
onDynamicInfo: function () {
this.onNext();
},
onDynamicTrack: function () {
this.onNext();
},
onPlaybackEdit: function () {
this.onNext();
},
onStop: function () {
this.childs.progress.box.width= 0;
window.Repaint();
},
onMouseMove: function () {
if ( this.mouseBtns & 1 ) fb.PlaybackTime= fb.PlaybackLength * this.mouseX / window.Width;
},
tagz: function (str) {
return str.replace ( /.*/mg , function(s) { return fb.TitleFormat(s).Eval() } );
}
}
var $= track_info;
есть мысль прикрутить к этому делу DOM, XML и CSS ^_^ фактически написать браузер... o_0 (мозилла, крепко затянувшись, побежала в угол)
буду рад критике и интересным идеям.